Disclaimer: The purpose of the Open Case Studies project is to demonstrate the use of various data science methods, tools, and software in the context of messy, real-world data. A given case study does not cover all aspects of the research process, is not claiming to be the most appropriate way to analyze a given data set, and should not be used in the context of making policy decisions without external consultation from scientific experts.

Motivation

A variety of different sources contribute different types of pollutants to what we call air pollution. Some sources are natural while others are anthropogenic (human derived):

[source]

Major types of air pollutants

  1. Gaseous - Carbon Monoxide (CO), Ozone (O3), Nitrogen Oxides(NO, NO2), Sulpher Dioxide (SO2)
  2. Particulate - small liquids and solids suspended in the air (includes lead- can include certain types of dust)
  3. Dust - small solids (larger than particulates) that can be suspended in the air for some time but eventually settle
  4. Biological - pollen, bacteria, viruses, mold spores

See [here])http://www.redlogenv.com/worker-safety/part-1-dust-and-particulate-matter) for more detail on the types of pollutants in the air.

Particulate pollution

Air pollution particulates are generally described by their size.

There are 3 major categories:

  1. Large Coarse Particulate Mater - has diameter of >10 micrometers (10 µm)

  2. Coarse Particulate Mater (called PM10-2.5) - has diameter of between 2.5 µm and 10 µm

  3. Fine Particulate Mater (called PM2.5) - has diameter of < 2.5 µm

PM10 includes any particulate mater <10 µm (both coarse and fine particulate mater)

Here you can see how these sizes compare with a human hair:

[source]

The following plot and table show the relative sizes of these different pollutants in micrometers(µm):

[source]

[source]

This table shows how deeply some of the smaller fine particles can penetrate within the human body:

[source]

Negative Impact of Particulate Exposure on Health

Exposure to air pollution is associated with higher rates of mortality in older adults and is known to be a risk factor for many diseases and conditions including but not limited to:

  1. Asthma - fine particle exposure (PM2.5) was found to be associated with higher rates of asthma in children
  2. Inflammation in type 1 diabetes - fine particle exposure (PM2.5) from traffic-related air pollution was associated with increased measures of inflammatory markers in youths with type 1 diabetes
  3. Lung function and emphysema - higher concentrations of ozone (O3), nitrogen oxides (NOx), black carbon, and fine particle exposure PM2.5 , at study baseline were significantly associated with greater increases in percent emphysema per 10 years
  4. Low birthweight - fine particle exposure(PM2.5) was associated with lower birth weight in full-term live births
  5. Viral Infection - higher rates of infection and increased severity of infection are associated with higher exposures to pollution levels including fine particle exposure (PM2.5)

See this review article for more information about sources of air pollution and the influence of air pollution on health.

Sparse Monitoring is Problematic for Public Health

Historically epidemiological studies would assess the influence of air pollution on health outcomes by relying on a number of monitors located around the country. However as can be seen in the following figure, these monitors remain to be relatively sparse in certain regions of the country. Furthermore, dramatic differences in pollution rates can be seen even within the same city.

[source]

This lack of granularity in air pollution monitoring has hindered our ability to discern the full impact of air pollution on health and to identify at-risk locations.

Machine Learning Offers a Solution

An article published in the Environmental Health journal dealt with this issue by using data about population density, road density, among other features to model or predict air pollution levels at a more localized scale using machine learning methods.

Yanosky, J. D. et al. Spatio-temporal modeling of particulate air pollution in the conterminous United States using geographic and meteorological predictors. Environ Health 13, 63 (2014).

The authors of this article state that:

“Exposure to atmospheric particulate matter (PM) remains an important public health concern, although it remains difficult to quantify accurately across large geographic areas with sufficiently high spatial resolution. Recent epidemiologic analyses have demonstrated the importance of spatially- and temporally-resolved exposure estimates, which show larger PM-mediated health effects as compared to nearest monitor or county-specific ambient concentrations.”

The article above explains that machine learning methods can be used to predict air pollution levels when traditional monitoring systems are not available in a particular area or when there is not enough spatial granularity with current monitoring systems. We will use similar methods to predict annual air pollution levels spatially within the US.

Main Questions

Our main question:

  1. Can we predict annual average air pollution concentrations at the granularity of zip code regional levels using predictors such as data about population density, urbanization, road density, as well as, satellite pollution data and chemical modeling data?

Learning Objectives

In this case study, we will walk you through importing data from CSV files and performing machine learning methods to predict our outcome variable of interest (in this case annual fine particle air pollution estimates). We will especially focus on using packages and functions from the Tidyverse, and more specifically the tidymodels package/ecosystem primarily developed and maintained by Max Kuhn and Davis Vaughan. This package loads more modeling related packages like rsample, recipes, parsnip, yardstick, and dials. We will also briefly cover the workflows and tune packages. The tidyverse is a library of packages created by RStudio. While some students may be familiar with previous R programming packages, these packages make data science in R especially efficient.

We will begin by loading the packages that we will need:

Package Use
here to easily load and save data
readr to import the CSV file data
dplyr to view/arrange/filter/select/compare specific subsets of the data
skimr to get an overview of data
summarytools to get an overview of data in a different style
magrittr to use the %<>% pipping operator
corrplot to make large correlation plots
ggcorrplot also to make large correlation plots
GGally to make smaller correlation plots
rsample to split the data into testing and training sets and to split the training set for cross-validation
recipes to pre-process data for modeling in a tidy and reproducible way and to extract pre-processed data (major functions are recipe() , prep() and various transformation step_*() functions, as well as juice() - extracts final preprocessed training data and bake() - applies recipe steps to testing data). See here for more info.
parsnip an interface to create models (major functions are fit(), set_engine())
yardstick to evaluate the performance of models

stringr | to manipulate the text within the PDF of the data

purrr | to perform functions on all columns of a tibble tibble | to create data objects that we can manipulate with dplyr/stringr/tidyr/purrr tidyr | to separate data within a column into multiple columns ggplot2 | to make visualizations with multiple layers ggpubr | to easily add regression line equations to plots forcats | to change details about factors (categorical variables) lmerTest| to perform linear mixed model testing car| to perform Levene’s Test of Homogeneity of Variances ggiraph| to make plots interactive ggforce| to modify facets in plots viridis| to plot in color palette that is easily interpreted by colorblind individuals cowplot | to allow plots to be combined ___

The first time we use a function, we will use the :: to indicate which package we are using. Unless we have overlapping function names, this is not necessary, but we will include it here to be informative about where the functions we will use come from.

Context

The State of Global Air is a report released every year to communicate the impact of air pollution on public health.

The State of Global Air 2019 report which uses data from 2017 stated that:

Air pollution is the fifth leading risk factor for mortality worldwide. It is responsible for more deaths than many better-known risk factors such as malnutrition, alcohol use, and physical inactivity. Each year, more people die from air pollution–related disease than from road traffic injuries or malaria.

The report also stated that:

In 2017, air pollution is estimated to have contributed to close to 5 million deaths globally — nearly 1 in every 10 deaths.

##### [source]

The State of Global Air 2018 report using data from 2016 which separated different types of air pollution, found that particulate pollution was particularly associated with mortality.

The 2019 report shows that the highest levels of fine particulate pollution occurs in Africa and Asia and that:

More than 90% of people worldwide live in areas exceeding the World Health Organization (WHO) Guideline for healthy air. More than half live in areas that do not even meet WHO’s least-stringent air quality target.

Looking at the US specifically, air pollution levels are generally improving. The US Environmental Protection Agency (EPA) also releases a report about air pollution levels called Our Nation’s Air.

[source]

However, air pollution continues to contribute to health risk for Americans, in particular in regions with higher than national average rates of pollution that actually at time exceed the world health organization’s recommended level. Thus it is necessary to obtain high spatial granularity in estimates of air pollution in order to identify locations where populations are experiencing harmful levels of exposure.

You can see that current air quality conditions at this website and you will notice variation across different cities.

Here were the conditions in Topeka Kansas when this was written:

It reports particulate values using what is called the Air Quality Index scale (AQI), this calculator indicates that 114 AQI is equivalent to 40.7 ug/m3 and is considered unhealthy for sensitive individuals. Thus some areas very much exceed the World Health Organization (WHO) annual exposure guideline (10 ug/m3) at certain times and this may adversely affect the health of people living in these locations.

Furthermore, adverse health effects have been associated with populations experiencing higher pollution exposure despite the levels being below suggested guidelines. Secondly, it appears that the composition of the particulate mater and the influence of other demographic factors may make specific populations more at risk for adverse health effects due to air pollution. See this article for more details.

The monitor data that we will use in this case study comes from a system of monitors in which roughly 90% are located within cities. Thus there is an equity issue in terms of capturing the air pollution levels of more rural areas. Therefore, to get a better sense of the pollution exposures for the individuals living in these areas, methods like machine learning can be very useful to estimate air pollution levels in areas with little to no monitoring.

Indeed, machine learning methods are in fact used to be able to estimate air pollution in these low monitoring areas so that we can make a map like this where we have annual estimates for all of the contiguous US:

[source]

This is what we aim to achieve in this case study.

Limitations

There are some important considerations regarding this data analysis to keep in mind:

  1. The data in our analysis does not include information about the composition of particulate mater. Different types of particulates may be more benign or deleterious for health outcomes.

  2. Outdoor pollution levels are not necessarily an indication of of individual exposures. People spend differing amounts of time indoors and outdoors and are exposed to different pollution levels indoors. People are now developing personal monitoring systems to track air pollution levels on the personal level.

Our analysis will use annual mean estimates, however pollution levels can vary greatly by season, day and even hour. There are data sources that have finer levels of temporal data, however we are interested in long term exposures, as these appear to be the most influential for health outcomes, so we chose to use annual level data.

What are the data?

In Machine Learning for prediction, there are two main types of variables:

  1. Outcome variable
  2. Predictor variables

The outcome variable is what are trying to predict. In building our model we actually have the outcome variable data, but we want to see how well our predictor variables can explain the variation in our outcome data. This gives us a sense of how well we can use the predictor variable data to predict our outcome variable levels when we in fact do not have data about the outcome.

As a simpler example, imagine that we have data about the sales and characteristics of cars from last year and we want to predict which cars might sell well this year. We do not have the sales data yet for this year, but we do know the characteristics of our cars for this year. We can use a model of the characteristics that explained sales last year to estimate what cars might sell well this year. In this case, our outcome variable is the sale performance of the cars, while the different characteristics of the cars make up our predictor or explanatory variables.

In this case study, we will evaluate air pollution monitor data of fine particulate mater (PM2.5) in the contiguous US from 2008, as well as data about population density, road density, urbanization levels, and NASA satellite data to develop models to predict localized air pollution levels.

The monitor data will be our outcome variable. We want to determine if we can predict air pollution levels based on other types of data, like road density and population density to see if we can use these data to predict air pollution in areas where there are no monitors.

Our outcome variable

The monitor data that we will be using comes from gravimetric monitors operated by the US Enivornmental Protection Agency (EPA). These monitors use a filtration system to specifically capture fine particulate matter. The weight of this matter is manually measured daily or weekly. See here for the EPA standard operating procedure for PM gravimetric analysis in 2008.

[source]

Here is an image of what the gravimetric monitors look like:

Gravimetric analysis is also used for emission testing. The same idea applies: a fresh filter is applied and the desired amount of time passes, then the filter is removed and weighed.

There are other monitoring systems that can provide hourly measurements, but we will not be using data from these monitors in our analysis. Gravimetric analysis is considered to be among the most accurate methods.

In our csv, the value column indicates the PM2.5 monitor average for 2008 in mass of fine particles/volume of air for 876 gravimetric monitors. The units are micro grams of fine particulate mater (PM) that is less than 2.5 micrometers in diameter per cubic meter of air - mass concentration (ug/m3). Recall the the WHO exposure guideline is < 10 ug/m3 on average annually for PM2.5.

Our predictor variables

There are 48 predictor variables with values for each of the 876 monitors included in our outcome variable. The data comes from the US Enivornmental Protection Agency (EPA), the National Aeronautics and Space Administration (NASA), the US Census, and the National Center for Health Statistics (NCHS).

Variable Details
id Monitor number
– the county number is indicated before the decimal
– the monitor number is indicated after the decimal
Example: 1073.0023 is Jefferson county (1073) and .0023 one of 8 monitors
fips Federal information processing standard number for the county where the monitor is located
– 5 digit id code for counties (zero is often the first value and sometimes is not shown)
– the first 2 numbers indicate the state
– the last three numbers indicate the county
Example: Alabama’s state code is 01 because it is first alphabetically
(note: Alaska and Hawaii are not included because they are not part of the contiguous US)
Lat Latitude of the monitor in degrees
Lon Longitude of the monitor in degrees
state State where the monitor is located
county County where the monitor is located
city City where the monitor is located
CMAQ Estimated values of air pollution from a computational model called Community Multiscale Air Quality (CMAQ)
– A monitoring system that simulates the physics of the atmosphere using chemistry and weather data to predict the air pollution
Does not use any of the PM2.5 gravimetric monitoring data. (There is a version that does use the gravimetric monitoring data, but not this one!)
– Data from the EPA
zcta Zip Code Tabulation Area where the monitor is located
– Postal Zip codes are converted into “generalized areal representations” that are non-overlapping
– Data from the 2010 Census
zcta_area Land area of the zip code area in meters squared
– Data from the 2010 Census
zcta_pop Population in the zip code area
– Data from the 2010 Census
imp_a500 Impervious surface measure
– Within a circle with a radius of 500 meters around the monitor
– Impervious surface are roads, concrete, parking lots, buildings
– This is a measure of development
imp_a1000 Impervious surface measure
– Within a circle with a radius of 1000 meters around the monitor
imp_a5000 Impervious surface measure
– Within a circle with a radius of 5000 meters around the monitor
imp_a10000 Impervious surface measure
– Within a circle with a radius of 10000 meters around the monitor
imp_a15000 Impervious surface measure
– Within a circle with a radius of 15000 meters around the monitor
county_area Land area of the county of the monitor in meters squared
county_pop Population of the county of the monitor
Log_dist_to_prisec Log (Natural log) distance to a primary or secondary road from the monitor
– Highway or major road
log_pri_length_5000 Count of primary road length in meters in a circle with a radius of 5000 meters around the monitor (Natural log)
– Highways only
log_pri_length_10000 Count of primary road length in meters in a circle with a radius of 10000 meters around the monitor (Natural log)
– Highways only
log_pri_length_15000 Count of primary road length in meters in a circle with a radius of 15000 meters around the monitor (Natural log)
– Highways only
log_pri_length_25000 Count of primary road length in meters in a circle with a radius of 25000 meters around the monitor (Natural log)
– Highways only
log_prisec_length_500 Count of primary and secondary road length in meters in a circle with a radius of 500 meters around the monitor (Natural log)
– Highway and secondary roads
log_prisec_length_1000 Count of primary and secondary road length in meters in a circle with a radius of 1000 meters around the monitor (Natural log)
– Highway and secondary roads
log_prisec_length_5000 Count of primary and secondary road length in meters in a circle with a radius of 5000 meters around the monitor (Natural log)
– Highway and secondary roads
log_prisec_length_10000 Count of primary and secondary road length in meters in a circle with a radius of 10000 meters around the monitor (Natural log)
– Highway and secondary roads
log_prisec_length_15000 Count of primary and secondary road length in meters in a circle with a radius of 15000 meters around the monitor (Natural log)
– Highway and secondary roads
log_prisec_length_25000 Count of primary and secondary road length in meters in a circle with a radius of 25000 meters around the monitor (Natural log)
– Highway and secondary roads
log_nei_2008_pm25_sum_10000 Tons of emissions from major sources data base (annual data) sum of all sources within a circle with a radius of 10000 meters of distance around the monitor (Natural log)
log_nei_2008_pm25_sum_15000 Tons of emissions from major sources data base (annual data) sum of all sources within a circle with a radius of 15000 meters of distance around the monitor (Natural log)
log_nei_2008_pm25_sum_25000 Tons of emissions from major sources data base (annual data) sum of all sources within a circle with a radius of 25000 meters of distance around the monitor (Natural log)
log_nei_2008_pm10_sum_10000 Tons of emissions from major sources data base (annual data) sum of all sources within a circle with a radius of 10000 meters of distance around the monitor (Natural log)
log_nei_2008_pm10_sum_15000 Tons of emissions from major sources data base (annual data) sum of all sources within a circle with a radius of 15000 meters of distance around the monitor (Natural log)
log_nei_2008_pm10_sum_25000 Tons of emissions from major sources data base (annual data) sum of all sources within a circle with a radius of 25000 meters of distance around the monitor (Natural log)
popdens_county Population density (number of people per kilometer squared area of the county)
popdens_zcta Population density (number of people per kilometer squared area of zcta)
nohs Percentage of people in zcta area where the monitor is that do not have a high school degree
– Data from the Census
somehs Percentage of people in zcta area where the monitor whose highest formal educational attainment was some high school education
– Data from the Census
hs Percentage of people in zcta area where the monitor whose highest formal educational attainment was completing a high school degree
– Data from the Census
somecollege Percentage of people in zcta area where the monitor whose highest formal educational attainment was completing some college education
– Data from the Census
associate Percentage of people in zcta area where the monitor whose highest formal educational attainment was completing an associate degree
– Data from the Census
bachelor Percentage of people in zcta area where the monitor whose highest formal educational attainment was a bachelor’s degree
– Data from the Census
grad Percentage of people in zcta area where the monitor whose highest formal educational attainment was a graduate degree
– Data from the Census
pov Percentage of people in zcta area where the monitor is that lived in poverty in 2008 - or would it have been 2007 guidelines??https://aspe.hhs.gov/2007-hhs-poverty-guidelines
– Data from the Census
hs_orless Percentage of people in zcta area where the monitor whose highest formal educational attainment was a high school degree or less (sum of nohs, somehs, and hs)
urc2013 2013 Urban-rural classification of the county where the monitor is located
– 6 category variable - 1 is totally urban 6 is completely rural
– Data from the National Center for Health Statistics](https://www.cdc.gov/nchs/index.htm){target="_blank"}
urc2006 2006 Urban-rural classification of the county where the monitor is located
– 6 category variable - 1 is totally urban 6 is completely rural
– Data from the National Center for Health Statistics
aod Aerosol Optical Depth measurement from a NASA satellite
– based on the defraction of a laser
– used as a proxy of particulate pollution
– unit-less - higher value indicates more pollution
– Data from NASA

Many of these predictor variables have to do with the circular area around the monitor called the “buffer”. These are illustrated in the following figure:

[source]

Data Import

We have one CSV file that contains both our single outcome variable and all of our predictor variables.

Let’s import our data into R now so that we can explore the data further. We will call our data object pm for particulate matter.

Data Exploration and Wrangling

The first step in performing a machine learning analysis is to explore the data to better understand the variables included in the data, as we may learn about important details about the data that we should keep in mind as we try to predict our outcome variable.

First let’s just get a general sense of our data. We can do that using the glimpse() function of the dplyr package (it is also in the tibble package).

We will also use the %>% pipe which can be used to define the input for later sequential steps. This will make more sense when we have multiple sequential steps using the same data object. To use the pipe notation we need to install and load dplyr as well.

For example here we will first grab the pm data object, then we use the glimpse() function on it based on the pipe notation.

Rows: 876
Columns: 50
$ id                          <dbl> 1003.001, 1027.000, 1033.100, 1049.100, 1…
$ value                       <dbl> 9.597647, 10.800000, 11.212174, 11.659091…
$ fips                        <dbl> 1003, 1027, 1033, 1049, 1055, 1069, 1073,…
$ lat                         <dbl> 30.49800, 33.28126, 34.75878, 34.28763, 3…
$ lon                         <dbl> -87.88141, -85.80218, -87.65056, -85.9683…
$ state                       <chr> "Alabama", "Alabama", "Alabama", "Alabama…
$ county                      <chr> "Baldwin", "Clay", "Colbert", "DeKalb", "…
$ city                        <chr> "Fairhope", "Ashland", "Muscle Shoals", "…
$ CMAQ                        <dbl> 8.098836, 9.766208, 9.402679, 8.534772, 9…
$ zcta                        <dbl> 36532, 36251, 35660, 35962, 35901, 36303,…
$ zcta_area                   <dbl> 190980522, 374132430, 16716984, 203836235…
$ zcta_pop                    <dbl> 27829, 5103, 9042, 8300, 20045, 30217, 90…
$ imp_a500                    <dbl> 0.01730104, 1.96972318, 19.17301038, 5.78…
$ imp_a1000                   <dbl> 1.4096021, 0.8531574, 11.1448962, 3.86764…
$ imp_a5000                   <dbl> 3.3360118, 0.9851479, 15.1786154, 1.23114…
$ imp_a10000                  <dbl> 1.9879187, 0.5208189, 9.7253870, 1.031646…
$ imp_a15000                  <dbl> 1.4386207, 0.3359198, 5.2472094, 0.973044…
$ county_area                 <dbl> 4117521611, 1564252280, 1534877333, 20126…
$ county_pop                  <dbl> 182265, 13932, 54428, 71109, 104430, 1015…
$ log_dist_to_prisec          <dbl> 4.648181, 7.219907, 5.760131, 3.721489, 5…
$ log_pri_length_5000         <dbl> 8.517193, 8.517193, 8.517193, 8.517193, 9…
$ log_pri_length_10000        <dbl> 9.210340, 9.210340, 9.274303, 10.409411, …
$ log_pri_length_15000        <dbl> 9.630228, 9.615805, 9.658899, 11.173626, …
$ log_pri_length_25000        <dbl> 11.32735, 10.12663, 10.15769, 11.90959, 1…
$ log_prisec_length_500       <dbl> 7.295356, 6.214608, 8.611945, 7.310155, 8…
$ log_prisec_length_1000      <dbl> 8.195119, 7.600902, 9.735569, 8.585843, 9…
$ log_prisec_length_5000      <dbl> 10.815042, 10.170878, 11.770407, 10.21420…
$ log_prisec_length_10000     <dbl> 11.88680, 11.40554, 12.84066, 11.50894, 1…
$ log_prisec_length_15000     <dbl> 12.205723, 12.042963, 13.282656, 12.35366…
$ log_prisec_length_25000     <dbl> 13.41395, 12.79980, 13.79973, 13.55979, 1…
$ log_nei_2008_pm25_sum_10000 <dbl> 0.318035438, 3.218632928, 6.573127301, 0.…
$ log_nei_2008_pm25_sum_15000 <dbl> 1.967358961, 3.218632928, 6.581917457, 3.…
$ log_nei_2008_pm25_sum_25000 <dbl> 5.067308, 3.218633, 6.875900, 4.887665, 4…
$ log_nei_2008_pm10_sum_10000 <dbl> 1.35588511, 3.31111648, 6.69187313, 0.000…
$ log_nei_2008_pm10_sum_15000 <dbl> 2.26783411, 3.31111648, 6.70127741, 3.350…
$ log_nei_2008_pm10_sum_25000 <dbl> 5.628728, 3.311116, 7.148858, 5.171920, 4…
$ popdens_county              <dbl> 44.265706, 8.906492, 35.460814, 35.330814…
$ popdens_zcta                <dbl> 145.716431, 13.639555, 540.887040, 40.718…
$ nohs                        <dbl> 3.3, 11.6, 7.3, 14.3, 4.3, 5.8, 7.1, 2.7,…
$ somehs                      <dbl> 4.9, 19.1, 15.8, 16.7, 13.3, 11.6, 17.1, …
$ hs                          <dbl> 25.1, 33.9, 30.6, 35.0, 27.8, 29.8, 37.2,…
$ somecollege                 <dbl> 19.7, 18.8, 20.9, 14.9, 29.2, 21.4, 23.5,…
$ associate                   <dbl> 8.2, 8.0, 7.6, 5.5, 10.1, 7.9, 7.3, 8.0, …
$ bachelor                    <dbl> 25.3, 5.5, 12.7, 7.9, 10.0, 13.7, 5.9, 17…
$ grad                        <dbl> 13.5, 3.1, 5.1, 5.8, 5.4, 9.8, 2.0, 8.7, …
$ pov                         <dbl> 6.1, 19.5, 19.0, 13.8, 8.8, 15.6, 25.5, 7…
$ hs_orless                   <dbl> 33.3, 64.6, 53.7, 66.0, 45.4, 47.2, 61.4,…
$ urc2013                     <dbl> 4, 6, 4, 6, 4, 4, 1, 1, 1, 1, 1, 1, 1, 2,…
$ urc2006                     <dbl> 5, 6, 4, 5, 4, 4, 1, 1, 1, 1, 1, 1, 1, 2,…
$ aod                         <dbl> 37.36364, 34.81818, 36.00000, 33.08333, 4…

We can see that there are 876 monitors and that we have 50 total variables - one of which is the outcome. In this case our outcome variable is called value.

Notice that some of the variables that we would think of as factors (categorical) are currently of class double as indicated by the <dbl> just to the right of the column names/variable names in the glimpse() output. For example the monitor ID (id), the Federal Information Processing Standard number for the county where the monitor was located (fips), as well as the zcta

Let’s convert these variables into factors. We can do this using the mutate_at() function of the dplyr package and the as.factor() base function.

In this case we are also using the magrittr assignment pipe or double pipe that looks like this %<>% of the magrittr package. This allows us use the pm data as input but also reassign the output to the same data object name.

Rows: 876
Columns: 50
$ id                          <fct> 1003.001, 1027.0001, 1033.1002, 1049.1003…
$ value                       <dbl> 9.597647, 10.800000, 11.212174, 11.659091…
$ fips                        <fct> 1003, 1027, 1033, 1049, 1055, 1069, 1073,…
$ lat                         <dbl> 30.49800, 33.28126, 34.75878, 34.28763, 3…
$ lon                         <dbl> -87.88141, -85.80218, -87.65056, -85.9683…
$ state                       <chr> "Alabama", "Alabama", "Alabama", "Alabama…
$ county                      <chr> "Baldwin", "Clay", "Colbert", "DeKalb", "…
$ city                        <chr> "Fairhope", "Ashland", "Muscle Shoals", "…
$ CMAQ                        <dbl> 8.098836, 9.766208, 9.402679, 8.534772, 9…
$ zcta                        <fct> 36532, 36251, 35660, 35962, 35901, 36303,…
$ zcta_area                   <dbl> 190980522, 374132430, 16716984, 203836235…
$ zcta_pop                    <dbl> 27829, 5103, 9042, 8300, 20045, 30217, 90…
$ imp_a500                    <dbl> 0.01730104, 1.96972318, 19.17301038, 5.78…
$ imp_a1000                   <dbl> 1.4096021, 0.8531574, 11.1448962, 3.86764…
$ imp_a5000                   <dbl> 3.3360118, 0.9851479, 15.1786154, 1.23114…
$ imp_a10000                  <dbl> 1.9879187, 0.5208189, 9.7253870, 1.031646…
$ imp_a15000                  <dbl> 1.4386207, 0.3359198, 5.2472094, 0.973044…
$ county_area                 <dbl> 4117521611, 1564252280, 1534877333, 20126…
$ county_pop                  <dbl> 182265, 13932, 54428, 71109, 104430, 1015…
$ log_dist_to_prisec          <dbl> 4.648181, 7.219907, 5.760131, 3.721489, 5…
$ log_pri_length_5000         <dbl> 8.517193, 8.517193, 8.517193, 8.517193, 9…
$ log_pri_length_10000        <dbl> 9.210340, 9.210340, 9.274303, 10.409411, …
$ log_pri_length_15000        <dbl> 9.630228, 9.615805, 9.658899, 11.173626, …
$ log_pri_length_25000        <dbl> 11.32735, 10.12663, 10.15769, 11.90959, 1…
$ log_prisec_length_500       <dbl> 7.295356, 6.214608, 8.611945, 7.310155, 8…
$ log_prisec_length_1000      <dbl> 8.195119, 7.600902, 9.735569, 8.585843, 9…
$ log_prisec_length_5000      <dbl> 10.815042, 10.170878, 11.770407, 10.21420…
$ log_prisec_length_10000     <dbl> 11.88680, 11.40554, 12.84066, 11.50894, 1…
$ log_prisec_length_15000     <dbl> 12.205723, 12.042963, 13.282656, 12.35366…
$ log_prisec_length_25000     <dbl> 13.41395, 12.79980, 13.79973, 13.55979, 1…
$ log_nei_2008_pm25_sum_10000 <dbl> 0.318035438, 3.218632928, 6.573127301, 0.…
$ log_nei_2008_pm25_sum_15000 <dbl> 1.967358961, 3.218632928, 6.581917457, 3.…
$ log_nei_2008_pm25_sum_25000 <dbl> 5.067308, 3.218633, 6.875900, 4.887665, 4…
$ log_nei_2008_pm10_sum_10000 <dbl> 1.35588511, 3.31111648, 6.69187313, 0.000…
$ log_nei_2008_pm10_sum_15000 <dbl> 2.26783411, 3.31111648, 6.70127741, 3.350…
$ log_nei_2008_pm10_sum_25000 <dbl> 5.628728, 3.311116, 7.148858, 5.171920, 4…
$ popdens_county              <dbl> 44.265706, 8.906492, 35.460814, 35.330814…
$ popdens_zcta                <dbl> 145.716431, 13.639555, 540.887040, 40.718…
$ nohs                        <dbl> 3.3, 11.6, 7.3, 14.3, 4.3, 5.8, 7.1, 2.7,…
$ somehs                      <dbl> 4.9, 19.1, 15.8, 16.7, 13.3, 11.6, 17.1, …
$ hs                          <dbl> 25.1, 33.9, 30.6, 35.0, 27.8, 29.8, 37.2,…
$ somecollege                 <dbl> 19.7, 18.8, 20.9, 14.9, 29.2, 21.4, 23.5,…
$ associate                   <dbl> 8.2, 8.0, 7.6, 5.5, 10.1, 7.9, 7.3, 8.0, …
$ bachelor                    <dbl> 25.3, 5.5, 12.7, 7.9, 10.0, 13.7, 5.9, 17…
$ grad                        <dbl> 13.5, 3.1, 5.1, 5.8, 5.4, 9.8, 2.0, 8.7, …
$ pov                         <dbl> 6.1, 19.5, 19.0, 13.8, 8.8, 15.6, 25.5, 7…
$ hs_orless                   <dbl> 33.3, 64.6, 53.7, 66.0, 45.4, 47.2, 61.4,…
$ urc2013                     <dbl> 4, 6, 4, 6, 4, 4, 1, 1, 1, 1, 1, 1, 1, 2,…
$ urc2006                     <dbl> 5, 6, 4, 5, 4, 4, 1, 1, 1, 1, 1, 1, 1, 2,…
$ aod                         <dbl> 37.36364, 34.81818, 36.00000, 33.08333, 4…

Great! Now we can see that these variables are now factors as indicated by <fct> after the variable name.

Packages to get a sense of the data

The skim() function of the skimr package is also really helpful for getting a general sense of your data.

Data summary
Name pm
Number of rows 876
Number of columns 50
_______________________
Column type frequency:
character 3
factor 3
numeric 44
________________________
Group variables None

Variable type: character

skim_variable n_missing complete_rate min max empty n_unique whitespace
state 0 1 4 20 0 49 0
county 0 1 3 20 0 471 0
city 0 1 4 48 0 607 0

Variable type: factor

skim_variable n_missing complete_rate ordered n_unique top_counts
id 0 1 FALSE 876 100: 1, 102: 1, 103: 1, 104: 1
fips 0 1 FALSE 569 170: 12, 603: 10, 261: 9, 107: 8
zcta 0 1 FALSE 842 475: 3, 110: 2, 160: 2, 290: 2

Variable type: numeric

skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
value 0 1 10.81 2.580000e+00 3.02 9.27 11.15 12.37 2.316000e+01 ▂▆▇▁▁
lat 0 1 38.48 4.620000e+00 25.47 35.03 39.30 41.66 4.840000e+01 ▁▃▅▇▂
lon 0 1 -91.74 1.496000e+01 -124.18 -99.16 -87.47 -80.69 -6.804000e+01 ▃▂▃▇▃
CMAQ 0 1 8.41 2.970000e+00 1.63 6.53 8.62 10.24 2.313000e+01 ▃▇▃▁▁
zcta_area 0 1 183173481.91 5.425989e+08 15459.00 14204601.75 37653560.50 160041508.25 8.164821e+09 ▇▁▁▁▁
zcta_pop 0 1 24227.58 1.777216e+04 0.00 9797.00 22014.00 35004.75 9.539700e+04 ▇▇▃▁▁
imp_a500 0 1 24.72 1.934000e+01 0.00 3.70 25.12 40.22 6.961000e+01 ▇▅▆▃▂
imp_a1000 0 1 24.26 1.802000e+01 0.00 5.32 24.53 38.59 6.750000e+01 ▇▅▆▃▁
imp_a5000 0 1 19.93 1.472000e+01 0.05 6.79 19.07 30.11 7.460000e+01 ▇▆▃▁▁
imp_a10000 0 1 15.82 1.381000e+01 0.09 4.54 12.36 24.17 7.209000e+01 ▇▃▂▁▁
imp_a15000 0 1 13.43 1.312000e+01 0.11 3.24 9.67 20.55 7.110000e+01 ▇▃▁▁▁
county_area 0 1 3768701992.12 6.212830e+09 33703512.00 1116536297.50 1690826566.50 2878192209.00 5.194723e+10 ▇▁▁▁▁
county_pop 0 1 687298.44 1.293489e+06 783.00 100948.00 280730.50 743159.00 9.818605e+06 ▇▁▁▁▁
log_dist_to_prisec 0 1 6.19 1.410000e+00 -1.46 5.43 6.36 7.15 1.045000e+01 ▁▁▃▇▁
log_pri_length_5000 0 1 9.82 1.080000e+00 8.52 8.52 10.05 10.73 1.205000e+01 ▇▂▆▅▂
log_pri_length_10000 0 1 10.92 1.130000e+00 9.21 9.80 11.17 11.83 1.302000e+01 ▇▂▇▇▃
log_pri_length_15000 0 1 11.50 1.150000e+00 9.62 10.87 11.72 12.40 1.359000e+01 ▆▂▇▇▃
log_pri_length_25000 0 1 12.24 1.100000e+00 10.13 11.69 12.46 13.05 1.436000e+01 ▅▃▇▇▃
log_prisec_length_500 0 1 6.99 9.500000e-01 6.21 6.21 6.21 7.82 9.400000e+00 ▇▁▂▂▁
log_prisec_length_1000 0 1 8.56 7.900000e-01 7.60 7.60 8.66 9.20 1.047000e+01 ▇▅▆▃▁
log_prisec_length_5000 0 1 11.28 7.800000e-01 8.52 10.91 11.42 11.83 1.278000e+01 ▁▁▃▇▃
log_prisec_length_10000 0 1 12.41 7.300000e-01 9.21 11.99 12.53 12.94 1.385000e+01 ▁▁▃▇▅
log_prisec_length_15000 0 1 13.03 7.200000e-01 9.62 12.59 13.13 13.57 1.441000e+01 ▁▁▃▇▅
log_prisec_length_25000 0 1 13.82 7.000000e-01 10.13 13.38 13.92 14.35 1.523000e+01 ▁▁▃▇▆
log_nei_2008_pm25_sum_10000 0 1 3.97 2.350000e+00 0.00 2.15 4.29 5.69 9.120000e+00 ▆▅▇▆▂
log_nei_2008_pm25_sum_15000 0 1 4.72 2.250000e+00 0.00 3.47 5.00 6.35 9.420000e+00 ▃▃▇▇▂
log_nei_2008_pm25_sum_25000 0 1 5.67 2.110000e+00 0.00 4.66 5.91 7.28 9.650000e+00 ▂▂▇▇▃
log_nei_2008_pm10_sum_10000 0 1 4.35 2.320000e+00 0.00 2.69 4.62 6.07 9.340000e+00 ▅▅▇▇▂
log_nei_2008_pm10_sum_15000 0 1 5.10 2.180000e+00 0.00 3.87 5.39 6.72 9.710000e+00 ▂▃▇▇▂
log_nei_2008_pm10_sum_25000 0 1 6.07 2.010000e+00 0.00 5.10 6.37 7.52 9.880000e+00 ▁▂▆▇▃
popdens_county 0 1 551.76 1.711510e+03 0.26 40.77 156.67 510.81 2.682191e+04 ▇▁▁▁▁
popdens_zcta 0 1 1279.66 2.757490e+03 0.00 101.15 610.35 1382.52 3.041884e+04 ▇▁▁▁▁
nohs 0 1 6.99 7.210000e+00 0.00 2.70 5.10 8.80 1.000000e+02 ▇▁▁▁▁
somehs 0 1 10.17 6.200000e+00 0.00 5.90 9.40 13.90 7.220000e+01 ▇▂▁▁▁
hs 0 1 30.32 1.140000e+01 0.00 23.80 30.75 36.10 1.000000e+02 ▂▇▂▁▁
somecollege 0 1 21.58 8.600000e+00 0.00 17.50 21.30 24.70 1.000000e+02 ▆▇▁▁▁
associate 0 1 7.13 4.010000e+00 0.00 4.90 7.10 8.80 7.140000e+01 ▇▁▁▁▁
bachelor 0 1 14.90 9.710000e+00 0.00 8.80 12.95 19.22 1.000000e+02 ▇▂▁▁▁
grad 0 1 8.91 8.650000e+00 0.00 3.90 6.70 11.00 1.000000e+02 ▇▁▁▁▁
pov 0 1 14.95 1.133000e+01 0.00 6.50 12.10 21.22 6.590000e+01 ▇▅▂▁▁
hs_orless 0 1 47.48 1.675000e+01 0.00 37.92 48.65 59.10 1.000000e+02 ▁▃▇▃▁
urc2013 0 1 2.92 1.520000e+00 1.00 2.00 3.00 4.00 6.000000e+00 ▇▅▃▂▁
urc2006 0 1 2.97 1.520000e+00 1.00 2.00 3.00 4.00 6.000000e+00 ▇▅▃▂▁
aod 0 1 43.70 1.956000e+01 5.00 31.66 40.17 49.67 1.430000e+02 ▃▇▁▁▁

Notice how there is a column called n_missing about the number of values that are missing. It looks like our data is very complete and we do not have any missing data. This is also indicated by the complete_rate variable, which shows the ratio of completeness, in our case all variables have a value of 1 indicating they are fully complete.

The n_unqiue column shows us the number of unique values for each of our columns. We can see that there are 49 states represented in the data, and we know that the data should be of the contiguous states. Let’s take a look to see which states are included:

# A tibble: 49 x 1
   state               
   <chr>               
 1 Alabama             
 2 Arizona             
 3 Arkansas            
 4 California          
 5 Colorado            
 6 Connecticut         
 7 Delaware            
 8 District Of Columbia
 9 Florida             
10 Georgia             
11 Idaho               
12 Illinois            
13 Indiana             
14 Iowa                
15 Kansas              
16 Kentucky            
17 Louisiana           
18 Maine               
19 Maryland            
20 Massachusetts       
21 Michigan            
22 Minnesota           
23 Mississippi         
24 Missouri            
25 Montana             
26 Nebraska            
27 Nevada              
28 New Hampshire       
29 New Jersey          
30 New Mexico          
31 New York            
32 North Carolina      
33 North Dakota        
34 Ohio                
35 Oklahoma            
36 Oregon              
37 Pennsylvania        
38 Rhode Island        
39 South Carolina      
40 South Dakota        
41 Tennessee           
42 Texas               
43 Utah                
44 Vermont             
45 Virginia            
46 Washington          
47 West Virginia       
48 Wisconsin           
49 Wyoming             

Looks like “District of Columbia” is being included as a state. We can see that indeed Alaska and Hawaii are not included in the data.

Here is another method of looking at the data using the dfSummary() function of the summarytoolspackage. We need to copy and paste the output into the rmarkdown.

Dimensions: 876 x 50
Duplicates: 0

No Variable Stats / Values Freqs (% of Valid) Graph Valid Missing
1 id
[factor]
1. 1003.001
2. 1027.0001
3. 1033.1002
4. 1049.1003
5. 1055.001
6. 1069.0003
7. 1073.0023
8. 1073.1005
9. 1073.1009
10. 1073.101
[ 866 others ]
1 ( 0.1%)
1 ( 0.1%)
1 ( 0.1%)
1 ( 0.1%)
1 ( 0.1%)
1 ( 0.1%)
1 ( 0.1%)
1 ( 0.1%)
1 ( 0.1%)
1 ( 0.1%)
866 (98.9%)
876
(100%)
0
(0%)
2 value
[numeric]
Mean (sd) : 10.8 (2.6)
min < med < max:
3 < 11.2 < 23.2
IQR (CV) : 3.1 (0.2)
875 distinct values 876
(100%)
0
(0%)
3 fips
[factor]
1. 1003
2. 1027
3. 1033
4. 1049
5. 1055
6. 1069
7. 1073
8. 1089
9. 1097
10. 1101
[ 559 others ]
1 ( 0.1%)
1 ( 0.1%)
1 ( 0.1%)
1 ( 0.1%)
1 ( 0.1%)
1 ( 0.1%)
8 ( 0.9%)
1 ( 0.1%)
2 ( 0.2%)
1 ( 0.1%)
858 (98.0%)
876
(100%)
0
(0%)
4 lat
[numeric]
Mean (sd) : 38.5 (4.6)
min < med < max:
25.5 < 39.3 < 48.4
IQR (CV) : 6.6 (0.1)
876 distinct values 876
(100%)
0
(0%)
5 lon
[numeric]
Mean (sd) : -91.7 (15)
min < med < max:
-124.2 < -87.5 < -68
IQR (CV) : 18.5 (-0.2)
876 distinct values 876
(100%)
0
(0%)
6 state
[character]
1. California
2. Ohio
3. Illinois
4. Indiana
5. North Carolina
6. Pennsylvania
7. Michigan
8. Florida
9. Georgia
10. Texas
[ 39 others ]
85 ( 9.7%)
44 ( 5.0%)
38 ( 4.3%)
36 ( 4.1%)
35 ( 4.0%)
32 ( 3.7%)
30 ( 3.4%)
29 ( 3.3%)
28 ( 3.2%)
27 ( 3.1%)
492 (56.2%)
876
(100%)
0
(0%)
7 county
[character]
1. Jefferson
2. Cook
3. Hamilton
4. Lake
5. Los Angeles
6. Wayne
7. Washington
8. Cuyahoga
9. Jackson
10. Madison
[ 461 others ]
18 ( 2.1%)
12 ( 1.4%)
11 ( 1.3%)
11 ( 1.3%)
10 ( 1.1%)
10 ( 1.1%)
9 ( 1.0%)
7 ( 0.8%)
7 ( 0.8%)
7 ( 0.8%)
774 (88.4%)
876
(100%)
0
(0%)
8 city
[character]
1. Not in a city
2. New York
3. Cleveland
4. Baltimore
5. Chicago
6. Detroit
7. Milwaukee
8. New Haven
9. Philadelphia
10. Springfield
[ 597 others ]
103 (11.8%)
9 ( 1.0%)
6 ( 0.7%)
5 ( 0.6%)
5 ( 0.6%)
5 ( 0.6%)
5 ( 0.6%)
5 ( 0.6%)
5 ( 0.6%)
5 ( 0.6%)
723 (82.5%)
876
(100%)
0
(0%)
9 CMAQ  | Me [numeric] an (sd) : 8.4 (3)  | 60 min < med < max:
1.6 < 8.6 < 23.1
IQR (CV) : 3.7 (0.4)
1 distinct values | ![ ](tmp/ds0109.png) | 87 6  | 0
(100%)
(0%)
10 zcta
[factor]
1. 1022
2. 1103
3. 1201
4. 1608
5. 1832
6. 1840
7. 1863
8. 1904
9. 2113
10. 2119
[ 832 others ]
1 ( 0.1%)
2 ( 0.2%)
1 ( 0.1%)
2 ( 0.2%)
1 ( 0.1%)
1 ( 0.1%)
1 ( 0.1%)
1 ( 0.1%)
1 ( 0.1%)
1 ( 0.1%)
864 (98.6%)
876
(100%)
0
(0%)
11 zcta_area
[numeric]
Mean (sd) : 183173481.9 (542598878.5)
min < med < max:
15459 < 37653560.5 < 8164820625
IQR (CV) : 145836906.5 (3)
842 distinct values 876
(100%)
0
(0%)
12 zcta_pop
[numeric]
Mean (sd) : 24227.6 (17772.2)
min < med < max:
0 < 22014 < 95397
IQR (CV) : 25207.8 (0.7)
837 distinct values 876
(100%)
0
(0%)
13 imp_a500
[numeric]
Mean (sd) : 24.7 (19.3)
min < med < max:
0 < 25.1 < 69.6
IQR (CV) : 36.5 (0.8)
816 distinct values 876
(100%)
0
(0%)
14 imp_a1000
[numeric]
Mean (sd) : 24.3 (18)
min < med < max:
0 < 24.5 < 67.5
IQR (CV) : 33.3 (0.7)
860 distinct values 876
(100%)
0
(0%)
15 imp_a5000
[numeric]
Mean (sd) : 19.9 (14.7)
min < med < max:
0.1 < 19.1 < 74.6
IQR (CV) : 23.3 (0.7)
870 distinct values 876
(100%)
0
(0%)
16 imp_a10000
[numeric]
Mean (sd) : 15.8 (13.8)
min < med < max:
0.1 < 12.4 < 72.1
IQR (CV) : 19.6 (0.9)
870 distinct values 876
(100%)
0
(0%)
17 imp_a15000
[numeric]
Mean (sd) : 13.4 (13.1)
min < med < max:
0.1 < 9.7 < 71.1
IQR (CV) : 17.3 (1)
870 distinct values 876
(100%)
0
(0%)
18 county_area
[numeric]
Mean (sd) : 3768701992.1 (6212829553.6)
min < med < max:
33703512 < 1690826566.5 < 51947229509
IQR (CV) : 1761655911.5 (1.6)
564 distinct values 876
(100%)
0
(0%)
19 county_pop
[numeric]
Mean (sd) : 687298.4 (1293488.7)
min < med < max:
783 < 280730.5 < 9818605
IQR (CV) : 642211 (1.9)
564 distinct values 876
(100%)
0
(0%)
20 log_dist_to_prisec
[numeric]
Mean (sd) : 6.2 (1.4)
min < med < max:
-1.5 < 6.4 < 10.5
IQR (CV) : 1.7 (0.2)
870 distinct values 876
(100%)
0
(0%)
21 log_pri_length_5000
[numeric]
Mean (sd) : 9.8 (1.1)
min < med < max:
8.5 < 10.1 < 12
IQR (CV) : 2.2 (0.1)
586 distinct values 876
(100%)
0
(0%)
22 log_pri_length_10000
[numeric]
Mean (sd) : 10.9 (1.1)
min < med < max:
9.2 < 11.2 < 13
IQR (CV) : 2 (0.1)
687 distinct values 876
(100%)
0
(0%)
23 log_pri_length_15000
[numeric]
Mean (sd) : 11.5 (1.1)
min < med < max:
9.6 < 11.7 < 13.6
IQR (CV) : 1.5 (0.1)
726 distinct values 876
(100%)
0
(0%)
24 log_pri_length_25000
[numeric]
Mean (sd) : 12.2 (1.1)
min < med < max:
10.1 < 12.5 < 14.4
IQR (CV) : 1.4 (0.1)
787 distinct values 876
(100%)
0
(0%)
25 log_prisec_length_500
[numeric]
Mean (sd) : 7 (1)
min < med < max:
6.2 < 6.2 < 9.4
IQR (CV) : 1.6 (0.1)
382 distinct values 876
(100%)
0
(0%)
26 log_prisec_length_1000
[numeric]
Mean (sd) : 8.6 (0.8)
min < med < max:
7.6 < 8.7 < 10.5
IQR (CV) : 1.6 (0.1)
591 distinct values 876
(100%)
0
(0%)
27 log_prisec_length_5000
[numeric]
Mean (sd) : 11.3 (0.8)
min < med < max:
8.5 < 11.4 < 12.8
IQR (CV) : 0.9 (0.1)
852 distinct values 876
(100%)
0
(0%)
28 log_prisec_length_10000
[numeric]
Mean (sd) : 12.4 (0.7)
min < med < max:
9.2 < 12.5 < 13.8
IQR (CV) : 1 (0.1)
867 distinct values 876
(100%)
0
(0%)
29 log_prisec_length_15000
[numeric]
Mean (sd) : 13 (0.7)
min < med < max:
9.6 < 13.1 < 14.4
IQR (CV) : 1 (0.1)
869 distinct values 876
(100%)
0
(0%)
30 log_prisec_length_25000
[numeric]
Mean (sd) : 13.8 (0.7)
min < med < max:
10.1 < 13.9 < 15.2
IQR (CV) : 1 (0.1)
870 distinct values 876
(100%)
0
(0%)
31 log_nei_2008_pm25_sum_10000
[numeric]
Mean (sd) : 4 (2.4)
min < med < max:
0 < 4.3 < 9.1
IQR (CV) : 3.5 (0.6)
828 distinct values 876
(100%)
0
(0%)
32 log_nei_2008_pm25_sum_15000
[numeric]
Mean (sd) : 4.7 (2.2)
min < med < max:
0 < 5 < 9.4
IQR (CV) : 2.9 (0.5)
855 distinct values 876
(100%)
0
(0%)
33 log_nei_2008_pm25_sum_25000
[numeric]
Mean (sd) : 5.7 (2.1)
min < med < max:
0 < 5.9 < 9.7
IQR (CV) : 2.6 (0.4)
860 distinct values 876
(100%)
0
(0%)
34 log_nei_2008_pm10_sum_10000
[numeric]
Mean (sd) : 4.3 (2.3)
min < med < max:
0 < 4.6 < 9.3
IQR (CV) : 3.4 (0.5)
829 distinct values 876
(100%)
0
(0%)
35 log_nei_2008_pm10_sum_15000
[numeric]
Mean (sd) : 5.1 (2.2)
min < med < max:
0 < 5.4 < 9.7
IQR (CV) : 2.8 (0.4)
855 distinct values 876
(100%)
0
(0%)
36 log_nei_2008_pm10_sum_25000
[numeric]
Mean (sd) : 6.1 (2)
min < med < max:
0 < 6.4 < 9.9
IQR (CV) : 2.4 (0.3)
860 distinct values 876
(100%)
0
(0%)
37 popdens_county
[numeric]
Mean (sd) : 551.8 (1711.5)
min < med < max:
0.3 < 156.7 < 26821.9
IQR (CV) : 470 (3.1)
564 distinct values 876
(100%)
0
(0%)
38 popdens_zcta
[numeric]
Mean (sd) : 1279.7 (2757.5)
min < med < max:
0 < 610.3 < 30418.8
IQR (CV) : 1281.4 (2.2)
840 distinct values 876
(100%)
0
(0%)
39 nohs
[numeric]
Mean (sd) : 7 (7.2)
min < med < max:
0 < 5.1 < 100
IQR (CV) : 6.1 (1)
215 distinct values 876
(100%)
0
(0%)
40 somehs
[numeric]
Mean (sd) : 10.2 (6.2)
min < med < max:
0 < 9.4 < 72.2
IQR (CV) : 8 (0.6)
230 distinct values 876
(100%)
0
(0%)
41 hs
[numeric]
Mean (sd) : 30.3 (11.4)
min < med < max:
0 < 30.8 < 100
IQR (CV) : 12.3 (0.4)
347 distinct values 876
(100%)
0
(0%)
42 somecollege
[numeric]
Mean (sd) : 21.6 (8.6)
min < med < max:
0 < 21.3 < 100
IQR (CV) : 7.2 (0.4)
240 distinct values 876
(100%)
0
(0%)
43 associate
[numeric]
Mean (sd) : 7.1 (4)
min < med < max:
0 < 7.1 < 71.4
IQR (CV) : 3.9 (0.6)
157 distinct values 876
(100%)
0
(0%)
44 bachelor
[numeric]
Mean (sd) : 14.9 (9.7)
min < med < max:
0 < 12.9 < 100
IQR (CV) : 10.4 (0.7)
301 distinct values 876
(100%)
0
(0%)
45 grad
[numeric]
Mean (sd) : 8.9 (8.6)
min < med < max:
0 < 6.7 < 100
IQR (CV) : 7.1 (1)
245 distinct values 876
(100%)
0
(0%)
46 pov
[numeric]
Mean (sd) : 15 (11.3)
min < med < max:
0 < 12.1 < 65.9
IQR (CV) : 14.7 (0.8)
345 distinct values 876
(100%)
0
(0%)
47 hs_orless
[numeric]
Mean (sd) : 47.5 (16.8)
min < med < max:
0 < 48.7 < 100
IQR (CV) : 21.2 (0.4)
464 distinct values 876
(100%)
0
(0%)
48 urc2013
[numeric]
Mean (sd) : 2.9 (1.5)
min < med < max:
1 < 3 < 6
IQR (CV) : 2 (0.5)
1 : 203 (23.2%)
2 : 163 (18.6%)
3 : 228 (26.0%)
4 : 123 (14.0%)
5 : 101 (11.5%)
6 : 58 ( 6.6%)
876
(100%)
0
(0%)
49 urc2006
[numeric]
Mean (sd) : 3 (1.5)
min < med < max:
1 < 3 < 6
IQR (CV) : 2 (0.5)
1 : 195 (22.3%)
2 : 162 (18.5%)
3 : 221 (25.2%)
4 : 127 (14.5%)
5 : 115 (13.1%)
6 : 56 ( 6.4%)
876
(100%)
0
(0%)
50 aod
[numeric]
Mean (sd) : 43.7 (19.6)
min < med < max:
5 < 40.2 < 143
IQR (CV) : 18 (0.4)
581 distinct values 876
(100%)
0
(0%)

We can see that for many variables there are many low values as the distribution shows two peaks, one near zero and another with a higher value. This is true for the imp variables (measures of development), the nei variables (measures of emission sources) and the road density variables. We can also see that the range of some of the variables is very large, in particular the area and population related variables.

Evaluate correlation among possible predictors

In prediction analyses, it is also useful to evaluate if any of the variables are correlated.

Intuitively we can expect some of our variables to be correlated.

Let’s first take a look at all of our numeric variabels with thecorrplot package: The corrplot package is another option to look at correlation among possible predictors. This is a great option if we have many predictors. First we need to create a correlation matrix using the cor() function of the stats package (which is loaded automatically).

Using ggcorplot

We can see that the the development variables (imp) variables are correlated with each other as we might expect. We also see that the road density variables seem to be correlated with each other, and the emission variables seem to be correlated with each other. We can take a closer look using the ggcorr() function and the ggpairs() function of the GGally package. To select our variables of interest we can use the select() function with the contains() function of the tidyr package.

First let’s look at the imp/development variables.

Indeed, we can see that imp_a1000 and imp_a500 are perfectly correlated, as well as imp_a10000, imp_a15000.

Now let’s take a look at the road density data:

We can see that while some of the road density variables are highly correlated with one another (or anti-correlated), there arr some variables that are less correlated with one another.

Finally let’s look at the emission variables.

We would also expect the population density data might correlate with some of these variables. Let’s take a look.

Interesting, so these variables don’t appear to be highly correlated, therefore we might need variables from each of the categories to predict our monitor PM2.5 pollution values.

We seem to have some pretty extreme population values though, so let’s see what happens when we take the log value.

Indeed this increased the correlation, but variables from each of these categories may still prove to be useful for prediction.

Data Analysis

Now that we have a sense of what our data is like we can get started with data analysis.

The tidymodels ecosystem

To perform our analysis we will be using the tidymodels suite of packages. You may be familiar with the older packages caret or mlr which are also for machine learning and modeling but are not a part of the tidyverse. Max Kuhn describes tidymodels like this:

“Other packages, such as caret and mlr, help to solve the R model API issue. These packages do a lot of other things too: preprocessing, model tuning, resampling, feature selection, ensembling, and so on. In the tidyverse, we strive to make our packages modular and parsnip is designed only to solve the interface issue. It is not designed to be a drop-in replacement for caret. The tidymodels package collection, which includes parsnip, has other packages for many of these tasks, and they are designed to work together. We are working towards higher-level APIs that can replicate and extend what the current model packages can do.”

The major benefits of tidymodels

  1. standardized workflow/format/notation across different types of algorithms
  2. can easily modify preprocessing, algorithm choice, and hyper-parameter tuning making optimization easy

The machine learning process

The tidymodels ecosystem - an overview

There are many packages in the tidymodels ecosystem which assist with the various steps of the machine learning process:

This is the overall process:

There are two distinct goals of supervised machine learning:

  1. Prediction
  2. Classification

We will be performing a prediction analysis (which is also refered to as regression), which aims to predict continuous outcome variables given a number of predictors/explanatory variables/features/parameters, as we have already described.

Classification on the other hand aims to discern or predict group identity for a categorical outcome based on a number of predictors/explanatory variables/features/parameters.

The overall process is the same in either case.

Splitting the Data

The first step after data exploration in machine learning analysis is to split the data into training and testing datasets.

The training dataset will be used to build and tune our model. This is the data that the model “learns” on.

The testing set will be used to evaluate the performance of our model in a more generalizable way. What do we mean by “generalizable”?

Remember that our main goal is to use our model to be able to predict air pollution levels in areas where there are no gravimetric monitors. Therefore, if our model is super good at predicting air pollution with the data that we use to build it, it might not do the best job for the areas where there are few to no monitors. This would cause us to have really good prediction accuracy and we might assume that we were going to do a good job estimating air pollution any time we use our model, but in fact this would likely not be the case. This situation is what we call overfitting .

Overfitting happens when we end up modeling not only the major relationships in our data but also the noise within our data.

[source]

If we get fairly good prediction with our testing set then we will know that our model can be applied to other data and will perform fairly well. We will discuss this more later.

We will not touch the testing set until we have completed optimizing our model with the training set. This will allow us to have a less biased evaluation of how well our model can do with other data besides the data used in the training set to build the model. Ideally you would also want a completely independent dataset to further test the performance of your model.

Here is a great description of the differences between testing and training datasets.

We will use the rsample package to perform this step.

Theinitial_split() function allows us to specify how we want to split our data. Typically data is split into 3/4 for training and 1/4 for testing.This is the default proportion and does not need to be specified. However you can change the proportion using the prop argument, which we will do that here for illustrative purposes. You can also specify a variable to stratify by with the strata argument. This is useful if you have imbalanced categorical variables and you would like to intentionally make sure that there are similar number of samples of the rarer categories in both the testing and training sets. Otherwise the split is performed randomly.

The strata argument causes the random sampling to be conducted within the stratification variable. The can help ensure that the number of data points in the training data is equivalent to the proportions in the original data set.

In the case with our dataset, perhaps we would like our training set to have similar proportions of monitors from each of the states as in the initial data. This might be useful if we want our model to be generalizable across all of the states.

We can see that indeed there are different proportions of monitors in each state by using the count() function of the dpyr package.

# A tibble: 49 x 2
   state                    n
   <chr>                <int>
 1 Alabama                 24
 2 Arizona                 17
 3 Arkansas                16
 4 California              85
 5 Colorado                15
 6 Connecticut             14
 7 Delaware                 7
 8 District Of Columbia     3
 9 Florida                 29
10 Georgia                 28
11 Idaho                    7
12 Illinois                38
13 Indiana                 36
14 Iowa                    20
15 Kansas                  10
16 Kentucky                22
17 Louisiana               17
18 Maine                    1
19 Maryland                15
20 Massachusetts           16
21 Michigan                30
22 Minnesota               17
23 Mississippi             12
24 Missouri                13
25 Montana                 16
26 Nebraska                 7
27 Nevada                   4
28 New Hampshire            7
29 New Jersey              23
30 New Mexico              10
31 New York                24
32 North Carolina          35
33 North Dakota             4
34 Ohio                    44
35 Oklahoma                10
36 Oregon                  17
37 Pennsylvania            32
38 Rhode Island             5
39 South Carolina          14
40 South Dakota             9
41 Tennessee                3
42 Texas                   27
43 Utah                    14
44 Vermont                  4
45 Virginia                20
46 Washington               8
47 West Virginia           14
48 Wisconsin               21
49 Wyoming                 12

If our dataset were large enough it might be nice then to stratify by state, but our data is unfortunately not large enough. We will show how one would do this though for illustrative purposes. This option is often more important for classification applications of machine learning than it is for prediction.

Since the split is performed randomly, it is a good idea to use the set.seed() base function to ensure that if your rerun your code that your split will be the same next time. We can see the number of monitors in our training, testing, and original data by typing in the name of our split object. The result will look like this: <training data sample number, testing data sample number, original sample number>

<Analysis/Assess/Total>
<584/292/876>

Importantly the initial_split function only determines what rows of our pm data frame should be assigned for training or testing, it does not actually split the data.

To extract the testing and training data we can use the training() and testing() functions also of the rsample package.

# A tibble: 48 x 2
   state                    n
   <chr>                <int>
 1 Alabama                 18
 2 Arizona                 12
 3 Arkansas                14
 4 California              54
 5 Colorado                12
 6 Connecticut              8
 7 Delaware                 6
 8 District Of Columbia     2
 9 Florida                 18
10 Georgia                 17
# … with 38 more rows
# A tibble: 48 x 2
   state                    n
   <chr>                <int>
 1 Alabama                  6
 2 Arizona                  5
 3 Arkansas                 2
 4 California              31
 5 Colorado                 3
 6 Connecticut              6
 7 Delaware                 1
 8 District Of Columbia     1
 9 Florida                 11
10 Georgia                 11
# … with 38 more rows

Variable Role Assignment and Preprocessing

In tidymodels we will create a recipe, which is a standardized format for a sequence of steps for processing the data.

This can be very useful because it makes testing out different pre-processing steps or different algorithms with the same pre-processing very easy and reproducible.

Creating a recipe specifies how a dataframe of predictors should be created - it specifies what variables to be used and the preprocessing steps but it does not execute these steps or create the dataframe of predictors.

List the ingredients / specify the variables with the recipe() function

The first thing to do to create a recipe is to specify which variables we will be using as our outcome and predictors using the recipe() function. In terms of the metaphor of baking, we can think of this as listing our ingredients. The naming convention for recipe object names is *_rec or rec.

In our case recall that our value variable, which is the average annual gravimetric monitor PM2.5 concentration in ug/m3. Our predictors are all the other variables except the monitor ID, which is an id variable.

The reason not to include this variable is because this variable includes the county number and a number designating which particular monitor the values came from of the monitors there are in that county. Since this number is arbitrary and the county information is also given in the data, and the fact that each monitor only has one value in the value variable, nothing is gained by including this variable and it may instead introduce noise. However, it is useful to keep this data to take a look at what is happening later. We will show you what to do in this case in just a bit.

The simplest recipe with no preprocessing steps, would be to simply list the outcome and predictor variables.

We can do so in two ways:

  1. Using formula notation
  2. Assigning roles to each variable

Let’s look at the first way using formula notation, which looks like this:

outcome(s) ~ predictor(s)

If in the case of multiple predictors or a multivariate situation with two outcomes, use a plus sign

outcome1 + outcome2 ~ predictor1 + predictor2

If we want to include all predictors we can use a period like so:

outcome_variable_name ~ .

Now with our data we will start by making a recipe for our training data. In the simplest case we might use all predictors like this:

Data Recipe

Inputs:

      role #variables
   outcome          1
 predictor         49

However, to deal with the id variable we could use the update_role() function of the recipes package:

Data Recipe

Inputs:

        role #variables
 id variable          1
     outcome          1
   predictor         48

We could also specify the outcome and predictors in the same way as the id variable. Please see here for examples of other roles for variables. The role can be actually be any value.

The order is important here, as we first make all variables predictors and then override this role for the outcome and id variable. We will use the everything() function of the dplyr package to start with all of the variables in train_pm.

Data Recipe

Inputs:

        role #variables
 id variable          1
     outcome          1
   predictor         48

If we want to take a look at our formula from our recipe we can do use the formula() function of the stats package.

value ~ fips + lat + lon + state + county + city + CMAQ + zcta + 
    zcta_area + zcta_pop + imp_a500 + imp_a1000 + imp_a5000 + 
    imp_a10000 + imp_a15000 + county_area + county_pop + log_dist_to_prisec + 
    log_pri_length_5000 + log_pri_length_10000 + log_pri_length_15000 + 
    log_pri_length_25000 + log_prisec_length_500 + log_prisec_length_1000 + 
    log_prisec_length_5000 + log_prisec_length_10000 + log_prisec_length_15000 + 
    log_prisec_length_25000 + log_nei_2008_pm25_sum_10000 + log_nei_2008_pm25_sum_15000 + 
    log_nei_2008_pm25_sum_25000 + log_nei_2008_pm10_sum_10000 + 
    log_nei_2008_pm10_sum_15000 + log_nei_2008_pm10_sum_25000 + 
    popdens_county + popdens_zcta + nohs + somehs + hs + somecollege + 
    associate + bachelor + grad + pov + hs_orless + urc2013 + 
    urc2006 + aod
<environment: 0x7fddad2b8900>

We can also view our recipe in more detail using the base summary() function.

# A tibble: 50 x 4
   variable type    role        source  
   <chr>    <chr>   <chr>       <chr>   
 1 id       nominal id variable original
 2 value    numeric outcome     original
 3 fips     nominal predictor   original
 4 lat      numeric predictor   original
 5 lon      numeric predictor   original
 6 state    nominal predictor   original
 7 county   nominal predictor   original
 8 city     nominal predictor   original
 9 CMAQ     numeric predictor   original
10 zcta     nominal predictor   original
# … with 40 more rows

List the preprocessing steps using the step functions of the recipe package

The other thing the recipes package allows for is specifying pre-processing steps using a variety of step*() functions.

This link and this link show the many options for recipe step functions.

There are step functions for a variety of purposes:

  1. Imputation – which means filling in missing values based on the existing data
  2. Transformation – which means changing all values of a variable in the same way, typically to make it more normal or easier to interpret)
  3. Discretization – which means converting continuous values into discrete or nominal values - binning for example to reduce the number of possible levels) (However this is generally not advisable!)
  4. Encoding / Creating Dummy Variables – which means creating a numeric code for categorical variables More on Dummy Variables and one hot encoding
  5. Data type conversions – which means changing from integer to factor or numeric to date etc.
  6. Interaction term addition to the model – which means that we would be modeling for predictors that would influence the capacity of each other to predict the outcome
  7. Normalization – which means centering and scaling the data to a similar range of values
  8. Dimensionality Reduction/ Signal Extraction – which means mathematically obtaining a new smaller set of variables that capture the variation or signal in the original variables (ex. Principal Component Analysis and Independent Component Analysis)
  9. Filtering – Filtering options for removing variables (ex. remove variables that are highly correlated to others or remove variables with very little variance and therefore likely little predictive capacity)
  10. Row operations – which means performing functions on the values within the rows (ex. rearranging, filtering, imputing)
  11. Checking functions – Sanity checks to look for missing values, to look at the variable classes etc.

All of the step functions look like step_* except for the check functions which look like check_*.

There are several ways to select what variables to apply steps to:
1) tidyselect methods: contains(), matches(), starts_with(), ends_with(), everything(), num_range()
2) based on the type: all_nominal(), all_numeric() , has_type() 3) based on the role: all_predictors(), all_outcomes(), has_role() 4) name - use the actual name of the variable/variables of interest

Let’s try adding some steps to our recipe.

We might consider log transforming our population and area variables (that aren’t densities) - let’s take a look at the range of these variables.

$zcta_area
[1]      15459 8164820625

$zcta_pop
[1]     0 95397

$county_area
[1]    33703512 51947229509

$county_pop
[1]     783 9818605

We can see that the range for each of these variables is quite large, we can log transform this data using the step_log() function of the recipes package.

We would also want to potentially one hot encode some of our categorical variables so that they can be used with certain algorithms. We can do this with the step_dummy() function and the one_hot = TRUE argument. Our fips variable includes a numeric code for state and county - and therefore is essentially a proxy for county. Since we already have county, we will just use it and keep the fips id as another ID variable.

We can remove the fips variable from the predictors using update_role() to make sure that the role is no longer "predictor". We can make the role anything we want actually, so we will keep it something identifiable.

We might also want to remove variables that appear to be redundant and are highly correlated with others, as we know from our exploratory data analysis that many of our variables are correlated with one another. We can do this using the step_corr() function.

It is also a good idea to remove variables with near-zero variance, which can be done with the step_nzv() function. Variables have low variance if all the values are very similar, the values are very sparse, or if they are highly imbalanced.

Examples where you might have near-zero variance variables include: ### I Struggled to find links for this… to back up my statements###

  1. Similar Values - If the population density was nearly the same for every zcta that contained a monitor, then knowing the population density near our monitorwould contribute little to our model in assisting us to predict monitor air pollution values.
  2. Sparse Data - If all of the monitors were in locations where the populations did not attend graduate school, then these values would mostly be zero, again this would do very little to help us distinguish our air pollution monitors.When many of the values are zero this is also called sparse data.
  3. Imbalanced Data If nearly all of the monitors were located in one particular state, and all the others only had one monitor each, then the real predictive value would simply be in knowing if a monitor is located in that particular state or not. In this case we don’t want to remove our variable, we just want to simplify it.

It is important to add the steps to the recipe in an order that makes sense just like with a cooking recipe.

Thus first we are going to create numeric values for our categorical variables, then we will look at correlation and near-zero variance. We don’t want to remove some of our variables, like the CMAQ and aod variables so we can make sure they are kept in the model by excluding them from those steps. If we specifically wanted to remove a predictor we could use step_rm().

Data Recipe

Inputs:

        role #variables
   county id          1
 id variable          1
     outcome          1
   predictor         47

Operations:

Dummy variables from state, county, city, zcta
Correlation filter on all_predictors, -, CMAQ, -, aod
Sparse, unbalanced variable filter on all_predictors, -, CMAQ, -, aod

Specifying the Model

So far we have used rsample to split the data and recipes to assign variable and to specify and prep our preprocessing (as well as to optionally extract the preprocessed data).

We will now use the parsnip package (which is similar to the previous caret package - and hence why it is named after the vegetable) to specify our model.

There are four aspects to define about our model:
1) the type of model (using specific funtions in parsnip like rand_forest(), logistic_reg() etc.)
2) the mode of learning - classification or regression (using the set_mode() function)
3) the package or engine that we will use to implement the type of model selected (using the set_engine() function)
4) any arguments necessary for the model/package selected (using the set_args()function - for example the mtry = argument for random forest which is the number of variables to be used as options for splitting at each tree node)

We are going to start our analysis with a linear regression but we will demonstrate how we can try different models.

The first thing we do is define what type of model we would like to use. See here for modeling [options]in parsnip.

Linear Regression Model Specification (regression)

OK. So far all we have told parsnip is we want to use a linear regression… Let’s tell parsnip more about what we want.

We would like to use the ordinary least squares method to fit our linear regression. So we will tell parsnip that we want to use the lm package to implement our linear regression (there are many options actually- such as rstan glmnet, keras, and sparklyr). We will do so by using the set_engine() function of the parsnip package.

Linear Regression Model Specification (regression)

Computational engine: lm 

In some cases some packages can do either classification or prediction, so it is a good idea to specify which mode you intend to perform. You can do this with the set_mode() function of the parsnip package, by using either set_mode("classification") or set_mode("regression").

Linear Regression Model Specification (regression)

Computational engine: lm 

Fitting the Model: two ways - workflows and parsnip

There are two w To fit our model we can use the parsnip package and then assess our fit using the yardstick package.

However a newer package called workflows allows us to keep track of both our preprocessing steps and our model specification. It also allows us to implement fancier optimizations in an automated way and it is currently being developed to also handle post-processing operations, so it is good to learn about it!

So we will now create a workflow with the recipe (our preprocessing specifications) that we made and the model that we just specified.

First we use the workflow() function of the workflows package to create a workflow.

Then we add our recipe with the add_recipe() function and we add our model with the add_model() function of the workflows package.

Note: We do not need to actually prep our recipe before using workflows!

══ Workflow ═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
Preprocessor: Recipe
Model: linear_reg()

── Preprocessor ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
3 Recipe Steps

● step_dummy()
● step_corr()
● step_nzv()

── Model ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Linear Regression Model Specification (regression)

Computational engine: lm 

Ah, nice. Notice how it tells us about both our preprocessing steps and our model specifications.

Now we can prepare the recipe (estimate the parameters) and fit the model to our training data all at once. Printing the output we can see the coefficients of the model.

══ Workflow [trained] ═════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
Preprocessor: Recipe
Model: linear_reg()

── Preprocessor ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
3 Recipe Steps

● step_dummy()
● step_corr()
● step_nzv()

── Model ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Call:
stats::lm(formula = formula, data = data)

Coefficients:
                (Intercept)                          lat  
                  2.265e+02                    3.639e-02  
                        lon                         CMAQ  
                  2.579e-02                    2.847e-01  
                  zcta_area                     zcta_pop  
                  3.638e-10                    7.880e-06  
                   imp_a500                   imp_a15000  
                  7.453e-03                   -1.140e-03  
                county_area                   county_pop  
                 -2.116e-11                   -2.156e-07  
         log_dist_to_prisec          log_pri_length_5000  
                  4.064e-02                   -1.842e-01  
       log_pri_length_25000        log_prisec_length_500  
                  7.936e-03                    2.572e-01  
     log_prisec_length_1000       log_prisec_length_5000  
                 -2.288e-02                    4.743e-01  
    log_prisec_length_10000      log_prisec_length_25000  
                 -1.410e-01                    4.658e-01  
log_nei_2008_pm10_sum_15000  log_nei_2008_pm10_sum_25000  
                  1.088e-01                    5.255e-02  
             popdens_county                 popdens_zcta  
                 -4.114e-05                   -1.816e-05  
                       nohs                       somehs  
                 -2.234e+00                   -2.270e+00  
                         hs                  somecollege  
                 -2.271e+00                   -2.274e+00  
                  associate                     bachelor  
                 -2.272e+00                   -2.277e+00  
                       grad                          pov  
                 -2.284e+00                    7.001e-03  
                  hs_orless                      urc2013  
                         NA                    2.153e-01  
                        aod         state_Not.California  
                  2.555e-02                   -3.445e+00  
         city_Not.in.a.city  
                  3.550e-01  

Otherwise we could have done this without the workflows package. Notice here we will used the processed training data (juiced_train) as opposed to the raw training data that we used with the workflow we created with workflows.

Remember that in this case, we need to write your model again! Recall that id and fips are ID variables and that values is our outcome of interest (the pm air pollution measure at each monitor).

Looking at model fit with broom

The broom package allows for an easy/tidy way to look at the fitted model:

tidy() grabs the coefficients from the model
glance() summarizes the model fit and gives us an idea about how well the model might perform augment() gives a 150 row observation level summary of the data and fit

These broom functions currently only work with parsnip objects not raw workflows objects. To use the tidy() function with workflows we need to first use the pull_workflow_fit() function.

# A tibble: 34 x 5
   term                     estimate    std.error statistic  p.value
   <chr>                       <dbl>        <dbl>     <dbl>    <dbl>
 1 state_Not.California -3.44        0.436            -7.91 1.45e-14
 2 CMAQ                  0.285       0.0430            6.61 8.90e-11
 3 aod                   0.0256      0.00575           4.45 1.06e- 5
 4 lon                   0.0258      0.00998           2.58 1.00e- 2
 5 county_pop           -0.000000216 0.0000000934     -2.31 2.14e- 2
 6 urc2013               0.215       0.101             2.13 3.35e- 2
 7 grad                 -2.28        1.20             -1.90 5.78e- 2
 8 bachelor             -2.28        1.20             -1.90 5.84e- 2
 9 somecollege          -2.27        1.20             -1.89 5.87e- 2
10 associate            -2.27        1.20             -1.89 5.90e- 2
# … with 24 more rows
# A tibble: 1 x 11
  r.squared adj.r.squared sigma statistic  p.value    df logLik   AIC   BIC
      <dbl>         <dbl> <dbl>     <dbl>    <dbl> <int>  <dbl> <dbl> <dbl>
1     0.433         0.399  2.08      12.7 1.02e-48    34 -1240. 2550. 2703.
# … with 2 more variables: deviance <dbl>, df.residual <int>
# A tibble: 584 x 42
   value   lat   lon  CMAQ zcta_area zcta_pop imp_a500 imp_a15000 county_area
   <dbl> <dbl> <dbl> <dbl>     <dbl>    <dbl>    <dbl>      <dbl>       <dbl>
 1  9.60  30.5 -87.9  8.10 190980522    27829   0.0173      1.44   4117521611
 2 10.8   33.3 -85.8  9.77 374132430     5103   1.97        0.336  1564252280
 3 11.2   34.8 -87.7  9.40  16716984     9042  19.2         5.25   1534877333
 4 12.4   34.0 -86.0  9.24 154069359    20045  16.5         5.16   1385618994
 5 10.5   31.2 -85.4  9.12 162685124    30217  19.1         4.74   1501737720
 6 15.6   33.6 -86.8 10.2   26929603     9010  41.8        17.5    2878192209
 7 12.4   33.3 -87.0 10.2  166239542    16140   1.70        4.30   2878192209
 8 11.1   33.5 -87.3  8.16 385566685     3699   0           0.162  3423328940
 9 14.6   33.5 -86.9 10.2   10636977    11458  43.6        15.6    2878192209
10 12.0   33.7 -86.7  9.30 150661846    21725   1.48        4.25   2878192209
# … with 574 more rows, and 33 more variables: county_pop <dbl>,
#   log_dist_to_prisec <dbl>, log_pri_length_5000 <dbl>,
#   log_pri_length_25000 <dbl>, log_prisec_length_500 <dbl>,
#   log_prisec_length_1000 <dbl>, log_prisec_length_5000 <dbl>,
#   log_prisec_length_10000 <dbl>, log_prisec_length_25000 <dbl>,
#   log_nei_2008_pm10_sum_15000 <dbl>, log_nei_2008_pm10_sum_25000 <dbl>,
#   popdens_county <dbl>, popdens_zcta <dbl>, nohs <dbl>, somehs <dbl>,
#   hs <dbl>, somecollege <dbl>, associate <dbl>, bachelor <dbl>, grad <dbl>,
#   pov <dbl>, hs_orless <dbl>, urc2013 <dbl>, aod <dbl>,
#   state_Not.California <dbl>, city_Not.in.a.city <dbl>, .fitted <dbl>,
#   .se.fit <dbl>, .resid <dbl>, .hat <dbl>, .sigma <dbl>, .cooksd <dbl>,
#   .std.resid <dbl>
[1] TRUE

OK, so we have fit our model on our training data, which means we have created a model to predict values of air pollution based on the predictors that we have included. Yay!

Let’s take a look at how well our model fit our training data:

        1         2         3         4         5         6         7         8 
 9.461664 10.429189 11.795351 11.139746 10.863402 11.091857 10.073411  8.189021 
        9        10        11        12        13        14        15        16 
11.517888 10.618367  9.557499 10.218323  9.865608 11.011802 12.139040 10.202025 
       17        18        19        20        21        22        23        24 
10.517763  9.548571  6.837646  7.472453  7.018230 10.126795 10.133236  9.582305 
       25        26        27        28        29        30        31        32 
 9.702583  6.862089  7.005665  8.477788  8.892971  9.244236 11.417965 10.464960 
       33        34        35        36        37        38        39        40 
 9.652665  9.943594 11.435373 10.090206 10.304301 11.188076 11.193689 10.767763 
       41        42        43        44        45        46        47        48 
10.722817  9.949272 10.521367  9.976252 11.955651 11.674338 13.902418 13.582229 
       49        50        51        52        53        54        55        56 
14.713622 11.219505 11.320158 15.169192  8.682176 13.357477 11.166948 14.162085 
       57        58        59        60        61        62        63        64 
13.128209 10.867659 12.557864 11.404720 14.609938 10.003168 11.917995  9.886651 
       65        66        67        68        69        70        71        72 
11.161819 12.326977 12.722475 11.439546 11.380029 14.615337 10.945608 12.754387 
       73        74        75        76        77        78        79        80 
11.464256 13.050833 11.162822 14.092701 10.025276 12.181293 12.573405 12.850499 
       81        82        83        84        85        86        87        88 
12.523434 13.398889  8.867379 12.250365 15.385913 10.726820 12.320977 12.282267 
       89        90        91        92        93        94        95        96 
10.903510 13.504498 10.678776 11.367829 14.267153 11.959658 14.860756 12.245437 
       97        98        99       100       101       102       103       104 
11.009600 12.303933 10.376440  9.254959  8.458964 10.797185  9.615059  8.319766 
      105       106       107       108       109       110       111       112 
 6.584026  8.480982  7.889599  8.520672  9.507922  9.460726 12.291791 10.315367 
      113       114       115       116       117       118       119       120 
 9.899759 10.270368  9.531778  8.476645 10.506159 10.457589 11.548915 12.211470 
      121       122       123       124       125       126       127       128 
12.754005 11.760960 11.527420 13.358326 12.970527 11.450112  9.662891  8.860986 
      129       130       131       132       133       134       135       136 
 9.630399  9.107099  9.336214 10.377070 10.913731 10.012413 11.655663  9.197286 
      137       138       139       140       141       142       143       144 
 9.895577  8.992575 11.062182 10.928292 11.173204  9.290713  9.462250  9.815623 
      145       146       147       148       149       150       151       152 
10.567132 10.041853 12.438193 12.837043 11.155833 11.068409 11.568628 10.646408 
      153       154       155       156       157       158       159       160 
11.120305 10.674787 11.342914 11.600863  9.872202 12.933636 12.330424 10.674265 
      161       162       163       164       165       166       167       168 
10.692636  8.591527  8.483559  8.277465  9.219110  7.999004  7.325638 10.668789 
      169       170       171       172       173       174       175       176 
10.442171 13.278721 12.987068 12.609307 12.139812 13.311952  9.560588 11.231509 
      177       178       179       180       181       182       183       184 
 9.614572 11.388626 11.027188 10.701644 10.408321 11.281993 11.952935 12.314095 
      185       186       187       188       189       190       191       192 
11.343060 12.301626 11.670473 11.538465 11.450721 12.583606  9.908812 11.957886 
      193       194       195       196       197       198       199       200 
12.476480 11.356784 11.408551 11.386678 11.371265 11.869010 11.386166 10.716040 
      201       202       203       204       205       206       207       208 
13.547182 13.430563 14.488555 13.382721 11.721882 13.138956 11.617227 12.919960 
      209       210       211       212       213       214       215       216 
11.610622 11.234236 12.441517 11.565354 11.775386 11.870380 11.612343 10.513345 
      217       218       219       220       221       222       223       224 
11.332066 11.356102  8.622875  9.342198 10.532866 11.075768 10.814015  9.148910 
      225       226       227       228       229       230       231       232 
10.259892  8.851762 10.150785 11.702025 11.247041  9.448320  8.715848 10.465157 
      233       234       235       236       237       238       239       240 
 9.063738  8.512195  9.359375  8.694810 12.250888 10.950829 11.172992 11.113227 
      241       242       243       244       245       246       247       248 
12.539577 11.130235 11.520853 13.270299 12.445247 11.641586 11.084325 11.681937 
      249       250       251       252       253       254       255       256 
12.903454 11.675062 11.868743 11.887980 12.142425 11.125280 10.206552 13.083514 
      257       258       259       260       261       262       263       264 
12.553520 13.232212 11.590232 11.070216 11.072157 11.721994 10.595329 14.228343 
      265       266       267       268       269       270       271       272 
13.651194 10.111261 12.956021 13.017707 10.712920 13.277355 11.914351 11.578296 
      273       274       275       276       277       278       279       280 
12.601671 13.808564 13.137512 11.706520 11.860984  9.304048 10.849169 10.160520 
      281       282       283       284       285       286       287       288 
10.957044 10.853018 11.595010 11.208375 11.222850 10.646720 10.875621 10.875865 
      289       290       291       292       293       294       295       296 
12.139867  9.344793  7.829627  7.419011 10.276070  8.595271 11.984527 10.025066 
      297       298       299       300       301       302       303       304 
11.658014 10.844432 13.668283 13.877468 11.842378 12.609642 12.315624  7.550419 
      305       306       307       308       309       310       311       312 
10.543817 10.140751 10.640678  9.986984 10.672587 12.808831  8.608027  8.762374 
      313       314       315       316       317       318       319       320 
 9.800301  8.990358 10.913175 10.986842  9.848777 10.184492 10.730669  8.925857 
      321       322       323       324       325       326       327       328 
 9.810568 11.051639 12.301691 13.244583 12.143078  7.420562  7.181852  8.115063 
      329       330       331       332       333       334       335       336 
 7.557550  7.598764  7.963658  6.033631  8.174960  7.009403  6.547324  6.721532 
      337       338       339       340       341       342       343       344 
10.495751 10.127753  8.447220  8.955561  9.111061  6.229223  7.721007  8.702168 
      345       346       347       348       349       350       351       352 
 9.796073 10.735891 10.674564  9.993831  9.387035 11.404517 12.718761 12.490109 
      353       354       355       356       357       358       359       360 
12.490096 12.868844 14.159822 11.862943 12.490662 12.814318 13.292919 11.342429 
      361       362       363       364       365       366       367       368 
11.790078 13.543314 12.475061 11.439849  9.501710  9.938767  8.662747  9.361561 
      369       370       371       372       373       374       375       376 
 7.333849  7.619211  8.424590  8.182639  8.244907 11.421981 12.598988 12.766756 
      377       378       379       380       381       382       383       384 
10.004449 11.846089 11.484665  8.502844  9.985085 14.093239 11.022401 10.343070 
      385       386       387       388       389       390       391       392 
10.870999 11.580658  8.164514  9.816118 13.810603 10.765304 10.679352  8.943409 
      393       394       395       396       397       398       399       400 
11.394455 10.988983 11.911609 11.169336 10.926602 11.106484 10.975384 10.570735 
      401       402       403       404       405       406       407       408 
10.800890 11.216585 11.003865 12.058352  8.979768 10.417642 10.840787  8.564483 
      409       410       411       412       413       414       415       416 
10.468748  7.722598  9.024726  8.627277  8.712337 12.306801 11.259834 12.135047 
      417       418       419       420       421       422       423       424 
12.909887 13.900961 14.613681 14.659878 14.516719 11.834130 12.835139 11.524950 
      425       426       427       428       429       430       431       432 
11.205715 12.690535 12.366608 12.257143 11.554346 11.571765 10.268979 13.831592 
      433       434       435       436       437       438       439       440 
12.488541 12.274712 11.792411 12.159000 11.286455 12.398744 12.720250 11.839790 
      441       442       443       444       445       446       447       448 
12.042530 10.616712 11.592961  8.680015 10.002905 10.098331  9.303447  8.025186 
      449       450       451       452       453       454       455       456 
 8.160942  7.701500  7.573096  6.440509  8.413890  7.573817  8.654901  6.527707 
      457       458       459       460       461       462       463       464 
 9.316892  9.239795  7.577079  7.234717  7.744910 10.396131 11.349235 10.531142 
      465       466       467       468       469       470       471       472 
11.286622 11.324207 11.904075 11.984744 11.254344 10.087881 12.491983 12.727448 
      473       474       475       476       477       478       479       480 
11.023725  9.843285 12.532214 10.909423 11.556938 11.246725 13.678810 10.995575 
      481       482       483       484       485       486       487       488 
13.406587 12.947436 11.536939 10.519024 10.614975 10.691272 12.606993 11.966835 
      489       490       491       492       493       494       495       496 
11.220192  9.923407 11.012463  9.424555 10.077508 10.808538 10.687251 11.438914 
      497       498       499       500       501       502       503       504 
12.408781 10.434905  8.167398  7.968639  7.492743  7.971856  7.794390  8.631370 
      505       506       507       508       509       510       511       512 
 7.279254  7.833077 10.330354 10.925965 10.909906  8.503572 12.117403 10.667929 
      513       514       515       516       517       518       519       520 
10.129061 10.550327  9.918316 11.522068 11.296737 11.553654 10.476981 11.941762 
      521       522       523       524       525       526       527       528 
10.578826 11.080807  9.211676 10.323909  9.621231  8.335038  8.188955  9.082492 
      529       530       531       532       533       534       535       536 
 8.075345  9.420944  8.314572  9.247623  8.538591  9.859266  7.647124  9.902155 
      537       538       539       540       541       542       543       544 
 8.546524  9.920558 11.604894 11.918312 12.416602 10.819737 11.466657 11.179962 
      545       546       547       548       549       550       551       552 
11.665760  9.817793 14.172912 10.192052 11.355575 13.772991  8.847900  7.970775 
      553       554       555       556       557       558       559       560 
 7.460673  8.349559  8.135941 11.447727 11.618942 11.936942 10.918982 11.041702 
      561       562       563       564       565       566       567       568 
 9.949377 11.499303 10.904615 11.689807 11.747444 11.380585 11.009586 10.850464 
      569       570       571       572       573       574       575       576 
11.602371 11.551376 12.485626 11.270907 10.170153 10.619552  9.784335  8.033726 
      577       578       579       580       581       582       583       584 
10.810373  8.993775  5.743434  8.959191  8.089329  6.061699  8.339742  6.931294 
# A tibble: 584 x 8
   value .fitted .se.fit .resid   .hat .sigma    .cooksd .std.resid
   <dbl>   <dbl>   <dbl>  <dbl>  <dbl>  <dbl>      <dbl>      <dbl>
 1  9.60    9.46   0.375  0.136 0.0324   2.09 0.00000433     0.0663
 2 10.8    10.4    0.383  0.371 0.0338   2.09 0.0000338      0.181 
 3 11.2    11.8    0.404 -0.583 0.0376   2.09 0.0000936     -0.285 
 4 12.4    11.1    0.388  1.24  0.0346   2.08 0.000384       0.604 
 5 10.5    10.9    0.426 -0.355 0.0418   2.09 0.0000388     -0.174 
 6 15.6    11.1    0.379  4.50  0.0332   2.08 0.00486        2.20  
 7 12.4    10.1    0.459  2.33  0.0485   2.08 0.00196        1.14  
 8 11.1     8.19   0.777  2.91  0.139    2.08 0.0108         1.51  
 9 14.6    11.5    0.378  3.03  0.0329   2.08 0.00219        1.48  
10 12.0    10.6    0.452  1.33  0.0470   2.08 0.000623       0.656 
# … with 574 more rows
        1         2         3         4         5         6         7         8 
 9.461664 10.429189 11.795351 11.139746 10.863402 11.091857 10.073411  8.189021 
        9        10        11        12        13        14        15        16 
11.517888 10.618367  9.557499 10.218323  9.865608 11.011802 12.139040 10.202025 
       17        18        19        20        21        22        23        24 
10.517763  9.548571  6.837646  7.472453  7.018230 10.126795 10.133236  9.582305 
       25        26        27        28        29        30        31        32 
 9.702583  6.862089  7.005665  8.477788  8.892971  9.244236 11.417965 10.464960 
       33        34        35        36        37        38        39        40 
 9.652665  9.943594 11.435373 10.090206 10.304301 11.188076 11.193689 10.767763 
       41        42        43        44        45        46        47        48 
10.722817  9.949272 10.521367  9.976252 11.955651 11.674338 13.902418 13.582229 
       49        50        51        52        53        54        55        56 
14.713622 11.219505 11.320158 15.169192  8.682176 13.357477 11.166948 14.162085 
       57        58        59        60        61        62        63        64 
13.128209 10.867659 12.557864 11.404720 14.609938 10.003168 11.917995  9.886651 
       65        66        67        68        69        70        71        72 
11.161819 12.326977 12.722475 11.439546 11.380029 14.615337 10.945608 12.754387 
       73        74        75        76        77        78        79        80 
11.464256 13.050833 11.162822 14.092701 10.025276 12.181293 12.573405 12.850499 
       81        82        83        84        85        86        87        88 
12.523434 13.398889  8.867379 12.250365 15.385913 10.726820 12.320977 12.282267 
       89        90        91        92        93        94        95        96 
10.903510 13.504498 10.678776 11.367829 14.267153 11.959658 14.860756 12.245437 
       97        98        99       100       101       102       103       104 
11.009600 12.303933 10.376440  9.254959  8.458964 10.797185  9.615059  8.319766 
      105       106       107       108       109       110       111       112 
 6.584026  8.480982  7.889599  8.520672  9.507922  9.460726 12.291791 10.315367 
      113       114       115       116       117       118       119       120 
 9.899759 10.270368  9.531778  8.476645 10.506159 10.457589 11.548915 12.211470 
      121       122       123       124       125       126       127       128 
12.754005 11.760960 11.527420 13.358326 12.970527 11.450112  9.662891  8.860986 
      129       130       131       132       133       134       135       136 
 9.630399  9.107099  9.336214 10.377070 10.913731 10.012413 11.655663  9.197286 
      137       138       139       140       141       142       143       144 
 9.895577  8.992575 11.062182 10.928292 11.173204  9.290713  9.462250  9.815623 
      145       146       147       148       149       150       151       152 
10.567132 10.041853 12.438193 12.837043 11.155833 11.068409 11.568628 10.646408 
      153       154       155       156       157       158       159       160 
11.120305 10.674787 11.342914 11.600863  9.872202 12.933636 12.330424 10.674265 
      161       162       163       164       165       166       167       168 
10.692636  8.591527  8.483559  8.277465  9.219110  7.999004  7.325638 10.668789 
      169       170       171       172       173       174       175       176 
10.442171 13.278721 12.987068 12.609307 12.139812 13.311952  9.560588 11.231509 
      177       178       179       180       181       182       183       184 
 9.614572 11.388626 11.027188 10.701644 10.408321 11.281993 11.952935 12.314095 
      185       186       187       188       189       190       191       192 
11.343060 12.301626 11.670473 11.538465 11.450721 12.583606  9.908812 11.957886 
      193       194       195       196       197       198       199       200 
12.476480 11.356784 11.408551 11.386678 11.371265 11.869010 11.386166 10.716040 
      201       202       203       204       205       206       207       208 
13.547182 13.430563 14.488555 13.382721 11.721882 13.138956 11.617227 12.919960 
      209       210       211       212       213       214       215       216 
11.610622 11.234236 12.441517 11.565354 11.775386 11.870380 11.612343 10.513345 
      217       218       219       220       221       222       223       224 
11.332066 11.356102  8.622875  9.342198 10.532866 11.075768 10.814015  9.148910 
      225       226       227       228       229       230       231       232 
10.259892  8.851762 10.150785 11.702025 11.247041  9.448320  8.715848 10.465157 
      233       234       235       236       237       238       239       240 
 9.063738  8.512195  9.359375  8.694810 12.250888 10.950829 11.172992 11.113227 
      241       242       243       244       245       246       247       248 
12.539577 11.130235 11.520853 13.270299 12.445247 11.641586 11.084325 11.681937 
      249       250       251       252       253       254       255       256 
12.903454 11.675062 11.868743 11.887980 12.142425 11.125280 10.206552 13.083514 
      257       258       259       260       261       262       263       264 
12.553520 13.232212 11.590232 11.070216 11.072157 11.721994 10.595329 14.228343 
      265       266       267       268       269       270       271       272 
13.651194 10.111261 12.956021 13.017707 10.712920 13.277355 11.914351 11.578296 
      273       274       275       276       277       278       279       280 
12.601671 13.808564 13.137512 11.706520 11.860984  9.304048 10.849169 10.160520 
      281       282       283       284       285       286       287       288 
10.957044 10.853018 11.595010 11.208375 11.222850 10.646720 10.875621 10.875865 
      289       290       291       292       293       294       295       296 
12.139867  9.344793  7.829627  7.419011 10.276070  8.595271 11.984527 10.025066 
      297       298       299       300       301       302       303       304 
11.658014 10.844432 13.668283 13.877468 11.842378 12.609642 12.315624  7.550419 
      305       306       307       308       309       310       311       312 
10.543817 10.140751 10.640678  9.986984 10.672587 12.808831  8.608027  8.762374 
      313       314       315       316       317       318       319       320 
 9.800301  8.990358 10.913175 10.986842  9.848777 10.184492 10.730669  8.925857 
      321       322       323       324       325       326       327       328 
 9.810568 11.051639 12.301691 13.244583 12.143078  7.420562  7.181852  8.115063 
      329       330       331       332       333       334       335       336 
 7.557550  7.598764  7.963658  6.033631  8.174960  7.009403  6.547324  6.721532 
      337       338       339       340       341       342       343       344 
10.495751 10.127753  8.447220  8.955561  9.111061  6.229223  7.721007  8.702168 
      345       346       347       348       349       350       351       352 
 9.796073 10.735891 10.674564  9.993831  9.387035 11.404517 12.718761 12.490109 
      353       354       355       356       357       358       359       360 
12.490096 12.868844 14.159822 11.862943 12.490662 12.814318 13.292919 11.342429 
      361       362       363       364       365       366       367       368 
11.790078 13.543314 12.475061 11.439849  9.501710  9.938767  8.662747  9.361561 
      369       370       371       372       373       374       375       376 
 7.333849  7.619211  8.424590  8.182639  8.244907 11.421981 12.598988 12.766756 
      377       378       379       380       381       382       383       384 
10.004449 11.846089 11.484665  8.502844  9.985085 14.093239 11.022401 10.343070 
      385       386       387       388       389       390       391       392 
10.870999 11.580658  8.164514  9.816118 13.810603 10.765304 10.679352  8.943409 
      393       394       395       396       397       398       399       400 
11.394455 10.988983 11.911609 11.169336 10.926602 11.106484 10.975384 10.570735 
      401       402       403       404       405       406       407       408 
10.800890 11.216585 11.003865 12.058352  8.979768 10.417642 10.840787  8.564483 
      409       410       411       412       413       414       415       416 
10.468748  7.722598  9.024726  8.627277  8.712337 12.306801 11.259834 12.135047 
      417       418       419       420       421       422       423       424 
12.909887 13.900961 14.613681 14.659878 14.516719 11.834130 12.835139 11.524950 
      425       426       427       428       429       430       431       432 
11.205715 12.690535 12.366608 12.257143 11.554346 11.571765 10.268979 13.831592 
      433       434       435       436       437       438       439       440 
12.488541 12.274712 11.792411 12.159000 11.286455 12.398744 12.720250 11.839790 
      441       442       443       444       445       446       447       448 
12.042530 10.616712 11.592961  8.680015 10.002905 10.098331  9.303447  8.025186 
      449       450       451       452       453       454       455       456 
 8.160942  7.701500  7.573096  6.440509  8.413890  7.573817  8.654901  6.527707 
      457       458       459       460       461       462       463       464 
 9.316892  9.239795  7.577079  7.234717  7.744910 10.396131 11.349235 10.531142 
      465       466       467       468       469       470       471       472 
11.286622 11.324207 11.904075 11.984744 11.254344 10.087881 12.491983 12.727448 
      473       474       475       476       477       478       479       480 
11.023725  9.843285 12.532214 10.909423 11.556938 11.246725 13.678810 10.995575 
      481       482       483       484       485       486       487       488 
13.406587 12.947436 11.536939 10.519024 10.614975 10.691272 12.606993 11.966835 
      489       490       491       492       493       494       495       496 
11.220192  9.923407 11.012463  9.424555 10.077508 10.808538 10.687251 11.438914 
      497       498       499       500       501       502       503       504 
12.408781 10.434905  8.167398  7.968639  7.492743  7.971856  7.794390  8.631370 
      505       506       507       508       509       510       511       512 
 7.279254  7.833077 10.330354 10.925965 10.909906  8.503572 12.117403 10.667929 
      513       514       515       516       517       518       519       520 
10.129061 10.550327  9.918316 11.522068 11.296737 11.553654 10.476981 11.941762 
      521       522       523       524       525       526       527       528 
10.578826 11.080807  9.211676 10.323909  9.621231  8.335038  8.188955  9.082492 
      529       530       531       532       533       534       535       536 
 8.075345  9.420944  8.314572  9.247623  8.538591  9.859266  7.647124  9.902155 
      537       538       539       540       541       542       543       544 
 8.546524  9.920558 11.604894 11.918312 12.416602 10.819737 11.466657 11.179962 
      545       546       547       548       549       550       551       552 
11.665760  9.817793 14.172912 10.192052 11.355575 13.772991  8.847900  7.970775 
      553       554       555       556       557       558       559       560 
 7.460673  8.349559  8.135941 11.447727 11.618942 11.936942 10.918982 11.041702 
      561       562       563       564       565       566       567       568 
 9.949377 11.499303 10.904615 11.689807 11.747444 11.380585 11.009586 10.850464 
      569       570       571       572       573       574       575       576 
11.602371 11.551376 12.485626 11.270907 10.170153 10.619552  9.784335  8.033726 
      577       578       579       580       581       582       583       584 
10.810373  8.993775  5.743434  8.959191  8.089329  6.061699  8.339742  6.931294 
# A tibble: 584 x 8
   value .fitted .se.fit .resid   .hat .sigma    .cooksd .std.resid
   <dbl>   <dbl>   <dbl>  <dbl>  <dbl>  <dbl>      <dbl>      <dbl>
 1  9.60    9.46   0.375  0.136 0.0324   2.09 0.00000433     0.0663
 2 10.8    10.4    0.383  0.371 0.0338   2.09 0.0000338      0.181 
 3 11.2    11.8    0.404 -0.583 0.0376   2.09 0.0000936     -0.285 
 4 12.4    11.1    0.388  1.24  0.0346   2.08 0.000384       0.604 
 5 10.5    10.9    0.426 -0.355 0.0418   2.09 0.0000388     -0.174 
 6 15.6    11.1    0.379  4.50  0.0332   2.08 0.00486        2.20  
 7 12.4    10.1    0.459  2.33  0.0485   2.08 0.00196        1.14  
 8 11.1     8.19   0.777  2.91  0.139    2.08 0.0108         1.51  
 9 14.6    11.5    0.378  3.03  0.0329   2.08 0.00219        1.48  
10 12.0    10.6    0.452  1.33  0.0470   2.08 0.000623       0.656 
# … with 574 more rows
[1] TRUE

Ok, so our fitted range appears to be smaller than the real values. We could probably do a bit better.

At this point we could take a look at the accuracy of our model performance, but we will only have one reference point: our testing dataset. And we haven’t done any tuning of our model or cross validation… so generally speaking you should not do this.

However if you were short on time you could continue like this.

Using the workflows method, you would need functions like this: tune::tune_*(), tune::fit_resamples() or tune::last_fit() from the tune package to get an assessment of fit.

We could stop here and use the yardstick package to evaluate performance. First we would want to use the model to predict values for the monitors in the testing data.

Using parsnip we need to use the baked data testing data.

# A tibble: 292 x 1
   .pred
   <dbl>
 1 10.4 
 2 10.5 
 3 10.3 
 4 10.4 
 5 10.6 
 6 12.9 
 7  9.53
 8  9.47
 9  8.82
10  7.67
# … with 282 more rows
# A tibble: 292 x 3
   .pred value fips 
   <dbl> <dbl> <fct>
 1 10.4  11.7  1049 
 2 10.5  13.1  1073 
 3 10.3  12.2  1073 
 4 10.4  12.2  1089 
 5 10.6  11.4  1103 
 6 12.9  12.2  1121 
 7  9.53 10.9  4013 
 8  9.47 10.6  4021 
 9  8.82 14.1  4023 
10  7.67  5.83 4025 
# … with 282 more rows

Let’s take a look at how well it did:

Say we were done optimizing our parameters we could then use the last_fit() function of the workflows package.

We could check out test performance using the collect_metrics() function of the tune package.

model performance :https://medium.com/@limavallantin/metrics-to-measure-machine-learning-model-performance-e8c963665476

Here you can see the predictions for the test set (the 292 rows with predicitions out of the 876 original monitor values) also using the tune package with the collect_predictions() function.

However we would really want to tune parameters and use cross validation for this.

yardstick can’t talk directly to workflows… need tune for that…

Cross validation sample splitting

We will use the rsample package again in order to further implement what are called cross validation techniques. This is also called resampling or repartioning. Note: we are not actually getting new samples from the underlying distribution so the term resampling is a bit of a misnomer.

Cross validation splits our training data into multiple training data sets to allow for an assessment of the accuracy of the model.

Here is a visualization of the concept for cross validation/resampling/repartitioning from Max Kuhn:

Technically creating our testing and training set out of our original training data is sometimes considered a form of cross validation called the holdout method. As we just learned this can give us a better sense of the accuracy of our data in a more generalizable way.

However, we can do a better job of optimizing our model for accuracy if we also perform another type of cross validation on the newly defined training set that we just created. There are many cross validation methods and most can be easily implemented using rsamples package. We will use a very popular method called either k-fold or v-fold cross validation.

This method involves essentially preforming the hold out method iteratively with the training data.

First the training set is divided into k or v equally sized smaller pieces.

Then the model is trained on the model on k-1 or v-1 subsets of the data iteratively (removing a different v or k untill all possible k-1 or v-1 sets have been evaluated) to get a sense of the performance of the model. This is really useful for fine tuning specific aspects of the model in a process called model tuning.

Here is a visualization of how the folds are created:

Note: People typically ignore spatial dependence with cross validation of air pollution monitoring data in the air pollution field, so we will do the same. However, it might make sense to leave out blocks of monitors rather than random individual monitors to help account for some spatial dependence.

The vfold_cv() function of the rsample package can be used to parse the training data into folds for k-fold/v-fold cross validation.

The v argument specifies the number of folds to create. The repeats argument specifies if any samples should be repeated across folds - defualt is FALSE The strata argument specifies a variable to stratify samples across folds (just like in initial_split()).

Again because these are created at random, we need to use the base set.seed() function in order to obtain the same results each time we knit this document. Generally speaking using 10 folds is good practice, but this depends on the variablity within your data. We are going to use 4 for the sake of expediency.

#  4-fold cross-validation 
# A tibble: 4 x 2
  splits            id   
  <list>            <chr>
1 <split [438/146]> Fold1
2 <split [438/146]> Fold2
3 <split [438/146]> Fold3
4 <split [438/146]> Fold4
NULL
NULL

Once the folds are created they can be used to evaluate peformance by fitting the model to each of the resamples that we created:

We can fit the model to our cross validation folds using the fit_resamples() function of the tune package, by specifying our workflow object and the cross validation fold object we just created. See here for more information.

We can now take a look at various metrics of performance based on the fit of our 10 cross validation “resamples”. To do this we will use the show_best() function of the tune package.

# A tibble: 1 x 5
  .metric .estimator  mean     n std_err
  <chr>   <chr>      <dbl> <int>   <dbl>
1 rmse    standard    2.18     4  0.0763

Tuning

Now let’s try some tuning.

Let’s take a closer look at how the monitor values vary with latitude and longitude.

We can see that there does not appear to be a single linear relationship for either of these predictors. Thus we might want to think about using splines or this(https://towardsdatascience.com/numerical-interpolation-natural-cubic-spline-52c1157b98ac) or just this(https://tidymodels.github.io/tune/articles/getting_started.html) or this(https://www.psych.mcgill.ca/misc/fda/ex-basis-b1.html) to model the relationship in our training data more closely. For example for the latitude plot (left) if we had 2 lines and one breakpoint called a knot around 40, with the first line having a positive slope and the second with a negative slope this would fit the data more similarly to the blue line shown in the figure.

We can tune for the number of knots by using a step function in the recipes package called step_ns() where ns stands for natural splines. In order to tune for the number of knots or degrees of freedom, we can set the deg_free argument to tune(). This is helpful, becuase we aren’t exactly sure how closely we should be following the relationship with the value and our longitude and latitude data in our training data to achieve good accuracy yet keep our model generalizable for other data.

This is when our cross validation methods become really handy. We can test out different values for the deg_free argument and see how our model performance varies across our training folds to try to find the optimal value.

We will update our recipe to add these steps. It is a good idea to do this for individual predictors because you can name each with the tune argument so that you can keep track of it later. We can see what we intend to tune with the parameters() function of the dials package.

See here for more information about implementing this in tidymodels.

Collection of 2 parameters for tuning

     id parameter type object class
 lon df       deg_free    nparam[+]
 lat df       deg_free    nparam[+]

Genearlly you could use the grid_*() functions of the dials package to create the different combinations of degrees of freedom to test for both variables to optimize the model. In our case we can visably see that if we add more than say 4 or 5 degrees of freedom we will likely overfit the data. So instead of using these functions we will create our own grid using the base seq() and expand.grid() functions.

  lon df lat df
1      1      1
2      3      1
3      5      1
4      1      3
5      3      3
6      5      3
7      1      5
8      3      5
9      5      5

Now we will tune this hyper-parameter (degrees of freedom) for both the lat and lon variables using our cross validation folds. To do this we will use the tune_grid() function of the tune package.

#  4-fold cross-validation 
# A tibble: 4 x 4
  splits            id    .metrics          .notes           
  <list>            <chr> <list>            <list>           
1 <split [438/146]> Fold1 <tibble [18 × 5]> <tibble [18 × 1]>
2 <split [438/146]> Fold2 <tibble [18 × 5]> <tibble [18 × 1]>
3 <split [438/146]> Fold3 <tibble [18 × 5]> <tibble [18 × 1]>
4 <split [438/146]> Fold4 <tibble [18 × 5]> <tibble [18 × 1]>
# A tibble: 18 x 7
   `lon df` `lat df` .metric .estimator  mean     n std_err
      <dbl>    <dbl> <chr>   <chr>      <dbl> <int>   <dbl>
 1        1        1 rmse    standard   2.18      4  0.0763
 2        1        1 rsq     standard   0.361     4  0.0486
 3        1        3 rmse    standard   2.13      4  0.0807
 4        1        3 rsq     standard   0.383     4  0.0388
 5        1        5 rmse    standard   2.13      4  0.0812
 6        1        5 rsq     standard   0.386     4  0.0403
 7        3        1 rmse    standard   2.10      4  0.0613
 8        3        1 rsq     standard   0.402     4  0.0296
 9        3        3 rmse    standard   2.05      4  0.0709
10        3        3 rsq     standard   0.428     4  0.0191
11        3        5 rmse    standard   2.03      4  0.0656
12        3        5 rsq     standard   0.439     4  0.0197
13        5        1 rmse    standard   2.11      4  0.0616
14        5        1 rsq     standard   0.397     4  0.0258
15        5        3 rmse    standard   2.05      4  0.0739
16        5        3 rsq     standard   0.427     4  0.0164
17        5        5 rmse    standard   2.02      4  0.0717
18        5        5 rsq     standard   0.442     4  0.0153
# A tibble: 18 x 7
   `lon df` `lat df` .metric .estimator  mean     n std_err
      <dbl>    <dbl> <chr>   <chr>      <dbl> <int>   <dbl>
 1        1        1 rmse    standard   2.18      4  0.0763
 2        1        1 rsq     standard   0.361     4  0.0486
 3        1        3 rmse    standard   2.13      4  0.0807
 4        1        3 rsq     standard   0.383     4  0.0388
 5        1        5 rmse    standard   2.13      4  0.0812
 6        1        5 rsq     standard   0.386     4  0.0403
 7        3        1 rmse    standard   2.10      4  0.0613
 8        3        1 rsq     standard   0.402     4  0.0296
 9        3        3 rmse    standard   2.05      4  0.0709
10        3        3 rsq     standard   0.428     4  0.0191
11        3        5 rmse    standard   2.03      4  0.0656
12        3        5 rsq     standard   0.439     4  0.0197
13        5        1 rmse    standard   2.11      4  0.0616
14        5        1 rsq     standard   0.397     4  0.0258
15        5        3 rmse    standard   2.05      4  0.0739
16        5        3 rsq     standard   0.427     4  0.0164
17        5        5 rmse    standard   2.02      4  0.0717
18        5        5 rsq     standard   0.442     4  0.0153
# A tibble: 1 x 7
  `lon df` `lat df` .metric .estimator  mean     n std_err
     <dbl>    <dbl> <chr>   <chr>      <dbl> <int>   <dbl>
1        5        5 rmse    standard    2.02     4  0.0717

Linear Regression Model with PCA

We can create another workflow to see how model pefromance compares using a different model. In this case we are going to peform something called Principal Component Analysis or PCA.

So what is PCA?

Let’s take a look to see what the step_pca function does to our predictors. To do so recall that we need to use the prep and juice functions of the recipes package on our recipe.

oper 1 step dummy [training] 
oper 2 step pca [training] 
The retained training set is ~ 0.13 Mb  in memory.
Rows: 584
Columns: 8
$ id    <fct> 1003.001, 1027.0001, 1033.1002, 1055.001, 1069.0003, 1073.0023,…
$ value <dbl> 9.597647, 10.800000, 11.212174, 12.375394, 10.508850, 15.591017…
$ fips  <fct> 1003, 1027, 1033, 1055, 1069, 1073, 1073, 1073, 1073, 1073, 107…
$ PC1   <dbl> -4120232815, -1570558844, -1534934869, -1388102571, -1504354268…
$ PC2   <dbl> -118909004, -346706197, 10140574, -129802253, -136385028, 23433…
$ PC3   <dbl> -72827.994, 7132.812, -56957.316, 45519.861, 36487.258, 448189.…
$ PC4   <dbl> -20385.63273, 1615.38773, -7187.37037, -15876.58640, -25852.952…
$ PC5   <dbl> -846.027447, 90.287809, 171.426032, -576.131718, -926.823714, -…

We still want to use the lm package for our regression so we can use the same model object:

Linear Regression Model Specification (regression)

Computational engine: lm 
══ Workflow ═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
Preprocessor: Recipe
Model: linear_reg()

── Preprocessor ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
2 Recipe Steps

● step_dummy()
● step_pca()

── Model ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Linear Regression Model Specification (regression)

Computational engine: lm 

Remember that using workflows we dont actually need to prep our recipe, we can just fit our model directly. So now we will use tune to fit our resamples… WAIT DOES THIS WORK?? or do you need to use fit…

Fit the cross validation samples:

Look at the performance:

# A tibble: 2 x 5
  .metric .estimator   mean     n std_err
  <chr>   <chr>       <dbl> <int>   <dbl>
1 rmse    standard   2.76       4  0.271 
2 rsq     standard   0.0527     4  0.0184

And we can compare this with our previous performance:

# A tibble: 2 x 5
  .metric .estimator  mean     n std_err
  <chr>   <chr>      <dbl> <int>   <dbl>
1 rmse    standard   2.18      4  0.0763
2 rsq     standard   0.361     4  0.0486

So we can see that our performance isn’t quite as good - especially if we look at the rmse value.

Let’s review everything:

check_new_values: This check will break the bake function if any of the checked columns does contain values it did not contain when prep was called on the recipe. If the check passes, nothing is changed to the data

check_range creates a specification of a recipe check that will check if the range of a numeric variable changed in the new data.

parameter vs hyperparameter

prepper for cross validation?

great blog about cross validation etc https://towardsdatascience.com/train-test-split-and-cross-validation-in-python-80b61beca4b6

Data Visualization

Summary

We have evaluated average consumption estimates of 15 dietary factors with probably non-communicable disease (NCD) risk from 195 different countries around the world. To do so we imported data from a PDF using the pdftools package, as well as data from two CSV files using readr. We used tidyverse packages such as dplyr, stringr, and tidy to clean and join the data from the PDF with the CSV files.

We learned that Regression is a powerful and flexible statistical tool that simplifies or estimates the relationships between variables using a mathematical model. We learned about the utility of the regression to compare groups, look for associations between variables, and to predict outcomes based on multiple predictor or explanatory variables. We then compared this to other popular tests like the \(t\)-test and the ANOVA. We learned that these tests are actually equivalent to specialized types of regressions.

Our statistical analysis focused on evaluating differences in the consumption of red meat around the world between females and males and across different age groups. First we looked at the assumptions of \(t\)-tests and regressions, and determined that the relative percentage data of red meat consumption to the optimal guideline suggested amount was right skewed. We learned that we could transform the data by taking the log of these values to achieve more normally distributed data. To compare males and females we used a \(t\)-test and learned that a \(t\)-test is a specialized form of a linear regression. To compare the 15 different age groups we used an ANOVA and learned that the ANOVA is also a specialized form of linear regression. We examined how we obtained the same results using either statistical test. This was also the case if we looked at the effect of gender and controlled for the paired country structure in the data by either including location_name in the model as another term or by using a mixed effects model to control for this structure as a random effect but not specifically test for the influence of location_name on red meat consumption estimates. We learned that fixed effects are those that we wish to evaluate, while random effects are those that may influence the relationships of our variables of interest but that we do not wish to actively evaluate. Using these tests and models, we determined that males consume more red meat than women on average around the world.

Our ANOVA analysis of age determined that indeed there at least one age group consumed a significantly different amount of red meat compared to the other age groups, and this was still the case when we controlled location_name. However, we learned that we could that the ANOVA does not provide information about which age groups are different. We learned how the regression however could provide some comparisons of different age groups relative to the reference age group. Furthermore, our data visualizations allowed us to determine that in general red met consumption appears to be higher in the younger age groups relative to the older age groups.

Finally, we also looked at differences in red meat consumption between the different countries and saw in our ANOVA analysis and our regression analysis that there were significant differences. We were able to use a regression that included sex, age_group_name, and location_name to evaluate the influence of each of the three demographic factors on consumption while controlling or accounting for the other two. Our results demonstrated that all three influenced or were associated with red meat consumption.

In preforming our statistical analyses we learned about the assumptions of the \(t\)-test, the regression, and the ANOVA. We also learned about important methods to tests these assumptions.

\(t\)-test assumptions:

  1. Normality of the data for both groups (this is not as much of an issue if the number of observations is relatively large total n>30 - can evaluate by plotting the distribution and by creating Q-Q plots)
  2. Equal variance between the two groups (make sure you do the correct test if the data is not normal)
  3. Balanced sample sizes of the two groups
  4. Independent observations (or independent paired observations)

We can evaluate if our data is normally distributed by plotting the distribution and by creating [Q-Q plots](Q-Q Plots to compare the distribution of our data to the theoretical normal distribution.

If our data is not normally distributed, we can consider these options:

  1. We can still perform a \(t\)-test if our n is large
  2. We can transform the data before performing a \(t\)-test
  3. We can use a nonparametric test (Wilcoxon signed rank test, the Wilcoxon rank sum test, and the Two-sample Kolmogorov-Smirnov (KS) test)
  4. We can perform a \(t\)-test with resampling methods (which should be especially considered when the groups are imbalanced)

See this case study for more information on \(t\)-test assumptions.

We learned that we can test if 2 groups have equal variance using:
1) the F test with var.test()
2) Mood’s test using mood.test() (use if the data is not normally distributed)

Linear regression assumptions:

L (linear) - There is a linear relationship between the variables.
I (independent) - The samples are independent from one another.
N (normal) - The residuals are normally distributed.
E (equal variances) - The variance of the residuals of the groups is similar.
It is also important that predictor variables are not correlated with one another.

ANOVA assumptions:

  1. Normality of the data for all tested groups (less of an issue if the number of observations is relatively large total n>30)
  2. Equal variance between the groups - aka Homogeneity of variance (make sure you do the correct test if the data is not normal)
  3. Balanced sample sizes of the groups
  4. Independent observations (or independent paired observations)

We learned about three tests for examining the equality of variance of 3 or more groups: 1) Bartlett’s test (works well if the data appears to be normally distributed) 2) Fligner-Killeen test is nonparametric and does not assume normality 3) Levene’s test, is more robust to violations of normality than the Bartlett’s test, but not as robust as the Fligner- Killeen test

Using the ggplot2 package we were able to visualize trends in the data and to compare consumption of these dietary factors in the US with that of the other countries. We see that the populations in many countries are over-consuming foods that are associated with health risk when over-consumed. In particular processed meat and sugar-sweetened beverages appear to be the most over consumed. Importantly both of these appear to be consumed at higher quantities by males and younger adults. People in the US appear to consume less sugar-sweetened beverages than other countries, however, people are still over-consuming. Processed meat however appears to be especially bad in the US. In terms of food that need to be consumed in adequate amounts to overcome health risk, nearly all countries for all factors are not reaching guideline levels. However, there are some countries consuming more than adequate amounts of legumes, vegetables, fruits and fiber. People in the US appear to eat more milk products and consume more omega-3 fatty acid and calcium rich foods than other countries. All countries including the US consume very low levels of polyunsaturated fatty acids. These polyunsaturated fatty acids are abundant in seeds, nuts, avocados, as well as fish. Likely the low level of consumption of nuts and seeds contributes to these low polyunsaturated fatty acid estimates. The supplementary table included in the article suggests that poor consumption of polyunsaturated fatty acids is associated with ischemic heart disease. The article takes this data further to evaluate the association of consumption levels of these foods with mortality.

Analyses like the one in our case study are important for defining which groups could benefit the most from interventions, education, and policy changes when attempting to mitigate public health challenges. You can see in the article however that many additional considerations would be involved to perform a more thorough analysis to adequately understand the data enough to recommend policy changes.

Suggested Homework

Students can evaluate consumption estimates of another dietary factor besides red meat.

LS0tCnRpdGxlOiAiT3BlbiBDYXNlIFN0dWRpZXMgOiBQcmVkaWN0aW5nIEFubnVhbCBBaXIgUG9sbHV0aW9uICIKY3NzOiBzdHlsZS5jc3MKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICBzZWxmX2NvbnRhaW5lZDogeWVzCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMKICAgIGhpZ2hsaWdodDogdGFuZ28KICAgIG51bWJlcl9zZWN0aW9uczogbm8KICAgIHRoZW1lOiBjb3NtbwogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDogeWVzCiAgcGRmX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKICB3b3JkX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKCi0tLQo8c3R5bGU+CiNUT0MgewogIGJhY2tncm91bmQ6IHVybCgiaHR0cHM6Ly9vcGVuY2FzZXN0dWRpZXMuZ2l0aHViLmlvL2ltZy9sb2dvLmpwZyIpOwogIGJhY2tncm91bmQtc2l6ZTogY29udGFpbjsKICBwYWRkaW5nLXRvcDogMjQwcHggIWltcG9ydGFudDsKICBiYWNrZ3JvdW5kLXJlcGVhdDogbm8tcmVwZWF0Owp9Cjwvc3R5bGU+CgoKCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGluY2x1ZGUgPSBUUlVFLCBjb21tZW50ID0gTkEsIGVjaG8gPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIGNhY2hlID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICBmaWcuYWxpZ24gPSAiY2VudGVyIiwgb3V0LndpZHRoID0gJzkwJScpCmxpYnJhcnkoaGVyZSkKbGlicmFyeShrbml0cikKYGBgCgoKIyMjIyB7Lm91dGxpbmUgfQpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQud2lkdGggPSAiODAwIHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgIm1haW5wbG90LnBuZyIpKQpgYGAKCiMjIyMKCiMjIHsuZGlzY2xhaW1lcl9ibG9ja30KCioqRGlzY2xhaW1lcioqOiBUaGUgcHVycG9zZSBvZiB0aGUgW09wZW4gQ2FzZSBTdHVkaWVzXShodHRwczovL29wZW5jYXNlc3R1ZGllcy5naXRodWIuaW8pe3RhcmdldD0iX2JsYW5rIn0gcHJvamVjdCBpcyAqKnRvIGRlbW9uc3RyYXRlIHRoZSB1c2Ugb2YgdmFyaW91cyBkYXRhIHNjaWVuY2UgbWV0aG9kcywgdG9vbHMsIGFuZCBzb2Z0d2FyZSBpbiB0aGUgY29udGV4dCBvZiBtZXNzeSwgcmVhbC13b3JsZCBkYXRhKiouIEEgZ2l2ZW4gY2FzZSBzdHVkeSBkb2VzIG5vdCBjb3ZlciBhbGwgYXNwZWN0cyBvZiB0aGUgcmVzZWFyY2ggcHJvY2VzcywgaXMgbm90IGNsYWltaW5nIHRvIGJlIHRoZSBtb3N0IGFwcHJvcHJpYXRlIHdheSB0byBhbmFseXplIGEgZ2l2ZW4gZGF0YSBzZXQsIGFuZCBzaG91bGQgbm90IGJlIHVzZWQgaW4gdGhlIGNvbnRleHQgb2YgbWFraW5nIHBvbGljeSBkZWNpc2lvbnMgd2l0aG91dCBleHRlcm5hbCBjb25zdWx0YXRpb24gZnJvbSBzY2llbnRpZmljIGV4cGVydHMuIAoKIyMgTW90aXZhdGlvbgpBIHZhcmlldHkgb2YgZGlmZmVyZW50IHNvdXJjZXMgY29udHJpYnV0ZSBkaWZmZXJlbnQgdHlwZXMgb2YgcG9sbHV0YW50cyB0byB3aGF0IHdlIGNhbGwgYWlyIHBvbGx1dGlvbi4gClNvbWUgc291cmNlcyBhcmUgbmF0dXJhbCB3aGlsZSBvdGhlcnMgYXJlIGFudGhyb3BvZ2VuaWMgKGh1bWFuIGRlcml2ZWQpOgoKPHAgYWxpZ249ImNlbnRlciI+CiAgPGltZyB3aWR0aD0iNjAwIiBzcmM9Imh0dHBzOi8vd3d3Lm5wcy5nb3Yvc3ViamVjdHMvYWlyL2ltYWdlcy9Tb3VyY2VzX0dyYXBoaWNfSHVnZS5qcGc/bWF4d2lkdGg9MTIwMCZtYXhoZWlnaHQ9MTIwMCZhdXRvcm90YXRlPWZhbHNlIj4KPC9wPgoKIyMjIyMgW1tzb3VyY2VdKGh0dHBzOi8vd3d3Lmdvb2dsZS5jb20vdXJsP3NhPWkmdXJsPWh0dHBzJTNBJTJGJTJGd3d3Lm5wcy5nb3YlMkZzdWJqZWN0cyUyRmFpciUyRnNvdXJjZXMuaHRtJnBzaWc9QU92VmF3MnY3QVZ4U0Y4WlNBUEVoTnVkVnRiTiZ1c3Q9MTU4NTc3MDk2NjIxNzAwMCZzb3VyY2U9aW1hZ2VzJmNkPXZmZSZ2ZWQ9MENBSVFqUnhxRndvVENQRE42NnFfeGVnQ0ZRQUFBQUFkQUFBQUFCQUQpXQoKIyMjIyBNYWpvciB0eXBlcyBvZiBhaXIgcG9sbHV0YW50cwoKMSkgKipHYXNlb3VzKiogLSBDYXJib24gTW9ub3hpZGUgKENPKSwgT3pvbmUgKE9+M34pLCBOaXRyb2dlbiBPeGlkZXMoTk8sIE5PfjJ+KSwgU3VscGhlciBEaW94aWRlIChTT34yfikKMikgKipQYXJ0aWN1bGF0ZSoqIC0gc21hbGwgbGlxdWlkcyBhbmQgc29saWRzIHN1c3BlbmRlZCBpbiB0aGUgYWlyIChpbmNsdWRlcyBsZWFkLSBjYW4gaW5jbHVkZSBjZXJ0YWluIHR5cGVzIG9mIGR1c3QpCjMpICoqRHVzdCoqIC0gc21hbGwgc29saWRzIChsYXJnZXIgdGhhbiBwYXJ0aWN1bGF0ZXMpIHRoYXQgY2FuIGJlIHN1c3BlbmRlZCBpbiB0aGUgYWlyIGZvciBzb21lIHRpbWUgYnV0IGV2ZW50dWFsbHkgc2V0dGxlCjQpICoqQmlvbG9naWNhbCoqIC0gcG9sbGVuLCBiYWN0ZXJpYSwgdmlydXNlcywgbW9sZCBzcG9yZXMKClNlZSBbaGVyZV0paHR0cDovL3d3dy5yZWRsb2dlbnYuY29tL3dvcmtlci1zYWZldHkvcGFydC0xLWR1c3QtYW5kLXBhcnRpY3VsYXRlLW1hdHRlcikgZm9yIG1vcmUgZGV0YWlsIG9uIHRoZSB0eXBlcyBvZiBwb2xsdXRhbnRzIGluIHRoZSBhaXIuCgoKIyMjIyBQYXJ0aWN1bGF0ZSBwb2xsdXRpb24gCgpBaXIgcG9sbHV0aW9uIHBhcnRpY3VsYXRlcyBhcmUgZ2VuZXJhbGx5IGRlc2NyaWJlZCBieSB0aGVpciAqKnNpemUqKi4KClRoZXJlIGFyZSAzIG1ham9yIGNhdGVnb3JpZXM6CgoxKSAqKkxhcmdlIENvYXJzZSoqIFBhcnRpY3VsYXRlIE1hdGVyIC0gaGFzIGRpYW1ldGVyIG9mID4xMCBtaWNyb21ldGVycyAoMTAgwrVtKSAKCjIpICoqQ29hcnNlKiogUGFydGljdWxhdGUgTWF0ZXIgKGNhbGxlZCAqKlBNfjEwLTIuNX4qKikgLSBoYXMgZGlhbWV0ZXIgb2YgYmV0d2VlbiAyLjUgwrVtIGFuZCAxMCDCtW0KCjMpICoqRmluZSoqIFBhcnRpY3VsYXRlIE1hdGVyIChjYWxsZWQgKipQTX4yLjV+KiopIC0gaGFzIGRpYW1ldGVyIG9mIDwgMi41IMK1bSAKCioqUE1+MTB+KiogaW5jbHVkZXMgYW55IHBhcnRpY3VsYXRlIG1hdGVyIDwxMCDCtW0gKGJvdGggY29hcnNlIGFuZCBmaW5lIHBhcnRpY3VsYXRlIG1hdGVyKQoKSGVyZSB5b3UgY2FuIHNlZSBob3cgdGhlc2Ugc2l6ZXMgY29tcGFyZSB3aXRoIGEgaHVtYW4gaGFpcjoKCmBgYHtyLCBlY2hvID0gRkFMU0UsIG91dC53aWR0aD0gIjYwMCBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJwbTIuNV9zY2FsZV9ncmFwaGljLWNvbG9yXzIuanBnIikpCmBgYAoKIyMjIyMgW1tzb3VyY2VdKGh0dHBzOi8vd3d3LmVwYS5nb3YvcG0tcG9sbHV0aW9uL3BhcnRpY3VsYXRlLW1hdHRlci1wbS1iYXNpY3MpXQoKPCEtLSA8cCBhbGlnbj0iY2VudGVyIj4gLS0+CjwhLS0gICA8aW1nIHdpZHRoPSI1MDAiIHNyYz0iaHR0cHM6Ly93d3cuc2Vuc2lyaW9uLmNvbS9pbWFnZXMvc2Vuc2lyaW9uLXNwZWNpYWxpc3QtYXJ0aWNsZS1maWd1cmUtMS1jZGQ3MC5qcGciPiAtLT4KPCEtLSA8L3A+IC0tPgoKCjx1PlRoZSBmb2xsb3dpbmcgcGxvdCBhbmQgdGFibGUgc2hvdyB0aGUgcmVsYXRpdmUgc2l6ZXMgb2YgdGhlc2UgZGlmZmVyZW50IHBvbGx1dGFudHMgaW4gbWljcm9tZXRlcnMowrVtKTo8L3U+Cgo8cCBhbGlnbj0iY2VudGVyIj4KICA8aW1nIHdpZHRoPSI2MDAiIHNyYz0iaHR0cHM6Ly91cGxvYWQud2lraW1lZGlhLm9yZy93aWtpcGVkaWEvY29tbW9ucy90aHVtYi9kL2RmL0FpcmJvcm5lLXBhcnRpY3VsYXRlLXNpemUtY2hhcnQuc3ZnLzgwMHB4LUFpcmJvcm5lLXBhcnRpY3VsYXRlLXNpemUtY2hhcnQuc3ZnLnBuZyI+CjwvcD4KCiMjIyMjIFtbc291cmNlXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9QYXJ0aWN1bGF0ZXMpXQoKCjxwIGFsaWduPSJjZW50ZXIiPgogIDxpbWcgd2lkdGg9IjUwMCIgc3JjPSJodHRwczovL3d3dy5mcm9udGllcnNpbi5vcmcvZmlsZXMvQXJ0aWNsZXMvNTA1NTcwL2ZwdWJoLTA4LTAwMDE0LUhUTUwvaW1hZ2VfbS9mcHViaC0wOC0wMDAxNC10MDAyLmpwZyI+CjwvcD4KCiMjIyMjIFtbc291cmNlXShodHRwczovL3d3dy5mcm9udGllcnNpbi5vcmcvYXJ0aWNsZXMvMTAuMzM4OS9mcHViaC4yMDIwLjAwMDE0L2Z1bGwpXQoKCjx1PlRoaXMgdGFibGUgc2hvd3MgaG93IGRlZXBseSBzb21lIG9mIHRoZSBzbWFsbGVyIGZpbmUgcGFydGljbGVzIGNhbiBwZW5ldHJhdGUgd2l0aGluIHRoZSBodW1hbiBib2R5OjwvdT4KCjxwIGFsaWduPSJjZW50ZXIiPgogIDxpbWcgd2lkdGg9IjUwMCIgc3JjPSJodHRwczovL3d3dy5mcm9udGllcnNpbi5vcmcvZmlsZXMvQXJ0aWNsZXMvNTA1NTcwL2ZwdWJoLTA4LTAwMDE0LUhUTUwvaW1hZ2VfbS9mcHViaC0wOC0wMDAxNC10MDAxLmpwZyI+CjwvcD4KCiMjIyMjIFtbc291cmNlXShodHRwczovL3d3dy5mcm9udGllcnNpbi5vcmcvYXJ0aWNsZXMvMTAuMzM4OS9mcHViaC4yMDIwLjAwMDE0L2Z1bGwpXQoKCiMjIyMgTmVnYXRpdmUgSW1wYWN0IG9mIFBhcnRpY3VsYXRlIEV4cG9zdXJlIG9uIEhlYWx0aCAKCkV4cG9zdXJlIHRvIGFpciBwb2xsdXRpb24gaXMgYXNzb2NpYXRlZCB3aXRoIGhpZ2hlciByYXRlcyBvZiBbbW9ydGFsaXR5XShodHRwczovL3d3dy5uY2JpLm5sbS5uaWguZ292L3BtYy9hcnRpY2xlcy9QTUM1NzgzMTg2Lyl7dGFyZ2V0PSJfYmxhbmsifSBpbiBvbGRlciBhZHVsdHMgYW5kIGlzIGtub3duIHRvIGJlIGEgcmlzayBmYWN0b3IgZm9yIG1hbnkgZGlzZWFzZXMgYW5kIGNvbmRpdGlvbnMgaW5jbHVkaW5nIGJ1dCBub3QgbGltaXRlZCB0bzoKCjEpIFtBc3RobWFdKGh0dHBzOi8vd3d3Lm5jYmkubmxtLm5paC5nb3YvcHVibWVkLzI5MjQzOTM3KXt0YXJnZXQ9Il9ibGFuayJ9IC0gZmluZSBwYXJ0aWNsZSBleHBvc3VyZSAoKipQTX4yLjV+KiopIHdhcyBmb3VuZCB0byBiZSBhc3NvY2lhdGVkIHdpdGggaGlnaGVyIHJhdGVzIG9mIGFzdGhtYSBpbiBjaGlsZHJlbgoyKSBbSW5mbGFtbWF0aW9uIGluIHR5cGUgMSBkaWFiZXRlc10oaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wdWJtZWQvMzE0MTk3NjUpe3RhcmdldD0iX2JsYW5rIn0gLSBmaW5lIHBhcnRpY2xlIGV4cG9zdXJlICgqKlBNfjIuNX4qKikgZnJvbSB0cmFmZmljLXJlbGF0ZWQgYWlyIHBvbGx1dGlvbiB3YXMgYXNzb2NpYXRlZCB3aXRoIGluY3JlYXNlZCBtZWFzdXJlcyBvZiBpbmZsYW1tYXRvcnkgbWFya2VycyBpbiB5b3V0aHMgd2l0aCB0eXBlIDEgZGlhYmV0ZXMKMykgW0x1bmcgZnVuY3Rpb24gYW5kIGVtcGh5c2VtYV0oaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wdWJtZWQvMzE0MDgxMzUpe3RhcmdldD0iX2JsYW5rIn0gLSBoaWdoZXIgY29uY2VudHJhdGlvbnMgb2Ygb3pvbmUgKE9+M34pLCBuaXRyb2dlbiBveGlkZXMgKE5Pfnh+KSwgYmxhY2sgY2FyYm9uLCBhbmQgZmluZSBwYXJ0aWNsZSBleHBvc3VyZSAqKlBNfjIuNX4qKiAsIGF0IHN0dWR5IGJhc2VsaW5lIHdlcmUgc2lnbmlmaWNhbnRseSBhc3NvY2lhdGVkIHdpdGggZ3JlYXRlciBpbmNyZWFzZXMgaW4gcGVyY2VudCBlbXBoeXNlbWEgcGVyIDEwIHllYXJzIAo0KSBbTG93IGJpcnRod2VpZ2h0XShodHRwczovL3d3dy5uY2JpLm5sbS5uaWguZ292L3B1Ym1lZC8zMTM4NjY0Myl7dGFyZ2V0PSJfYmxhbmsifSAtIGZpbmUgcGFydGljbGUgZXhwb3N1cmUoKipQTX4yLjV+KiopIHdhcyBhc3NvY2lhdGVkIHdpdGggbG93ZXIgYmlydGggd2VpZ2h0IGluIGZ1bGwtdGVybSBsaXZlIGJpcnRocwo1KSBbVmlyYWwgSW5mZWN0aW9uXShodHRwczovL3d3dy50YW5kZm9ubGluZS5jb20vZG9pL2Z1bGwvMTAuMTA4MC8wODk1ODM3MDcwMTY2NTQzNCl7dGFyZ2V0PSJfYmxhbmsifSAtIGhpZ2hlciByYXRlcyBvZiBpbmZlY3Rpb24gYW5kIGluY3JlYXNlZCBzZXZlcml0eSBvZiBpbmZlY3Rpb24gYXJlIGFzc29jaWF0ZWQgd2l0aCBoaWdoZXIgZXhwb3N1cmVzIHRvIHBvbGx1dGlvbiBsZXZlbHMgaW5jbHVkaW5nIGZpbmUgcGFydGljbGUgZXhwb3N1cmUgKCoqUE1+Mi41fioqKQoKU2VlIHRoaXMgW3JldmlldyBhcnRpY2xlXShodHRwczovL3d3dy5mcm9udGllcnNpbi5vcmcvYXJ0aWNsZXMvMTAuMzM4OS9mcHViaC4yMDIwLjAwMDE0L2Z1bGwpe3RhcmdldD0iX2JsYW5rIn0gZm9yIG1vcmUgaW5mb3JtYXRpb24gYWJvdXQgc291cmNlcyBvZiBhaXIgcG9sbHV0aW9uIGFuZCB0aGUgaW5mbHVlbmNlIG9mIGFpciBwb2xsdXRpb24gb24gaGVhbHRoLgoKIyMjIyBTcGFyc2UgTW9uaXRvcmluZyBpcyBQcm9ibGVtYXRpYyBmb3IgUHVibGljIEhlYWx0aAoKSGlzdG9yaWNhbGx5IGVwaWRlbWlvbG9naWNhbCBzdHVkaWVzIHdvdWxkIGFzc2VzcyB0aGUgaW5mbHVlbmNlIG9mIGFpciBwb2xsdXRpb24gb24gaGVhbHRoIG91dGNvbWVzIGJ5IHJlbHlpbmcgb24gYSBudW1iZXIgb2YgbW9uaXRvcnMgbG9jYXRlZCBhcm91bmQgdGhlIGNvdW50cnkuIEhvd2V2ZXIgYXMgY2FuIGJlIHNlZW4gaW4gdGhlIGZvbGxvd2luZyBmaWd1cmUsIHRoZXNlIG1vbml0b3JzIHJlbWFpbiB0byBiZSByZWxhdGl2ZWx5IHNwYXJzZSBpbiBjZXJ0YWluIHJlZ2lvbnMgb2YgdGhlIGNvdW50cnkuIEZ1cnRoZXJtb3JlLCBkcmFtYXRpYyBkaWZmZXJlbmNlcyBpbiBwb2xsdXRpb24gcmF0ZXMgY2FuIGJlIHNlZW4gZXZlbiB3aXRoaW4gdGhlIHNhbWUgY2l0eS4KCjxwIGFsaWduPSJjZW50ZXIiPgogIDxpbWcgd2lkdGg9IjQwMCIgc3JjPSJodHRwczovL3d3dy5uY2JpLm5sbS5uaWguZ292L3BtYy9hcnRpY2xlcy9QTUM0MTM3MjcyL2Jpbi8xNDc2LTA2OVgtMTMtNjMtMS5qcGciPgo8L3A+CgojIyMjIyBbW3NvdXJjZV0oaHR0cHM6Ly9laGpvdXJuYWwuYmlvbWVkY2VudHJhbC5jb20vYXJ0aWNsZXMvMTAuMTE4Ni8xNDc2LTA2OVgtMTMtNjMpXQoKVGhpcyBsYWNrIG9mIGdyYW51bGFyaXR5IGluIGFpciBwb2xsdXRpb24gbW9uaXRvcmluZyBoYXMgaGluZGVyZWQgb3VyIGFiaWxpdHkgdG8gZGlzY2VybiB0aGUgZnVsbCBpbXBhY3Qgb2YgYWlyIHBvbGx1dGlvbiBvbiBoZWFsdGggYW5kIHRvIGlkZW50aWZ5IGF0LXJpc2sgbG9jYXRpb25zLiAKCgojIyMjIE1hY2hpbmUgTGVhcm5pbmcgT2ZmZXJzIGEgU29sdXRpb24KCkFuIFthcnRpY2xlXShodHRwczovL2Voam91cm5hbC5iaW9tZWRjZW50cmFsLmNvbS9hcnRpY2xlcy8xMC4xMTg2LzE0NzYtMDY5WC0xMy02Myl7dGFyZ2V0PSJfYmxhbmsifSBwdWJsaXNoZWQgaW4gdGhlICpFbnZpcm9ubWVudGFsIEhlYWx0aCogam91cm5hbCBkZWFsdCB3aXRoIHRoaXMgaXNzdWUgYnkgdXNpbmcgZGF0YSBhYm91dCBwb3B1bGF0aW9uIGRlbnNpdHksIHJvYWQgZGVuc2l0eSwgYW1vbmcgb3RoZXIgZmVhdHVyZXMgdG8gbW9kZWwgb3IgcHJlZGljdCBhaXIgcG9sbHV0aW9uIGxldmVscyBhdCBhIG1vcmUgbG9jYWxpemVkIHNjYWxlIHVzaW5nIG1hY2hpbmUgbGVhcm5pbmcgbWV0aG9kcy4gCgpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQud2lkdGg9ICI4MDAgcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAidGhlcGFwZXIucG5nIikpCmBgYAoKIyMjIyB7LnJlZmVyZW5jZV9ibG9ja30KWWFub3NreSwgSi4gRC4gZXQgYWwuIFNwYXRpby10ZW1wb3JhbCBtb2RlbGluZyBvZiBwYXJ0aWN1bGF0ZSBhaXIgcG9sbHV0aW9uIGluIHRoZSBjb250ZXJtaW5vdXMgVW5pdGVkIFN0YXRlcyB1c2luZyBnZW9ncmFwaGljIGFuZCBtZXRlb3JvbG9naWNhbCBwcmVkaWN0b3JzLiAqRW52aXJvbiBIZWFsdGgqIDEzLCA2MyAoMjAxNCkuCgojIyMjCgpUaGUgYXV0aG9ycyBvZiB0aGlzIGFydGljbGUgc3RhdGUgdGhhdDoKCj4gIkV4cG9zdXJlIHRvIGF0bW9zcGhlcmljIHBhcnRpY3VsYXRlIG1hdHRlciAoUE0pIHJlbWFpbnMgYW4gaW1wb3J0YW50IHB1YmxpYyBoZWFsdGggY29uY2VybiwKYWx0aG91Z2ggaXQgcmVtYWlucyBkaWZmaWN1bHQgdG8gcXVhbnRpZnkgYWNjdXJhdGVseSBhY3Jvc3MgbGFyZ2UgZ2VvZ3JhcGhpYyBhcmVhcyB3aXRoIHN1ZmZpY2llbnRseSBoaWdoIHNwYXRpYWwKcmVzb2x1dGlvbi4gUmVjZW50IGVwaWRlbWlvbG9naWMgYW5hbHlzZXMgaGF2ZSBkZW1vbnN0cmF0ZWQgdGhlIGltcG9ydGFuY2Ugb2Ygc3BhdGlhbGx5LSBhbmQgdGVtcG9yYWxseS1yZXNvbHZlZApleHBvc3VyZSBlc3RpbWF0ZXMsIHdoaWNoIHNob3cgbGFyZ2VyIFBNLW1lZGlhdGVkIGhlYWx0aCBlZmZlY3RzIGFzIGNvbXBhcmVkIHRvIG5lYXJlc3QgbW9uaXRvciBvcgpjb3VudHktc3BlY2lmaWMgYW1iaWVudCBjb25jZW50cmF0aW9ucy4iIAoKCmBgYHtyLCBlY2hvID0gRkFMU0UsIG91dC53aWR0aD0gIjcwMCBweCIsIGV2YWwgPSBGQUxTRX0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgImRlYXRocy5wbmciKSkKYGBgCgpUaGUgYXJ0aWNsZSBhYm92ZSBleHBsYWlucyB0aGF0IG1hY2hpbmUgbGVhcm5pbmcgbWV0aG9kcyBjYW4gYmUgdXNlZCB0byBwcmVkaWN0IGFpciBwb2xsdXRpb24gbGV2ZWxzIHdoZW4gdHJhZGl0aW9uYWwgbW9uaXRvcmluZyBzeXN0ZW1zIGFyZSBub3QgYXZhaWxhYmxlIGluIGEgcGFydGljdWxhciBhcmVhIG9yIHdoZW4gdGhlcmUgaXMgbm90IGVub3VnaCBzcGF0aWFsIGdyYW51bGFyaXR5IHdpdGggY3VycmVudCBtb25pdG9yaW5nIHN5c3RlbXMuIFdlIHdpbGwgdXNlIHNpbWlsYXIgbWV0aG9kcyB0byBwcmVkaWN0IGFubnVhbCBhaXIgcG9sbHV0aW9uIGxldmVscyBzcGF0aWFsbHkgd2l0aGluIHRoZSBVUy4KCgojIyMgTWFpbiBRdWVzdGlvbnMKCiMjIyMgey5tYWluX3F1ZXN0aW9uX2Jsb2NrfQo8Yj48dT4gT3VyIG1haW4gcXVlc3Rpb246IDwvdT48L2I+CgoxKSBDYW4gd2UgcHJlZGljdCBhbm51YWwgYXZlcmFnZSBhaXIgcG9sbHV0aW9uIGNvbmNlbnRyYXRpb25zIGF0IHRoZSBncmFudWxhcml0eSBvZiB6aXAgY29kZSByZWdpb25hbCBsZXZlbHMgdXNpbmcgcHJlZGljdG9ycyBzdWNoIGFzIGRhdGEgYWJvdXQgcG9wdWxhdGlvbiBkZW5zaXR5LCB1cmJhbml6YXRpb24sIHJvYWQgZGVuc2l0eSwgYXMgd2VsbCBhcywgc2F0ZWxsaXRlIHBvbGx1dGlvbiBkYXRhIGFuZCBjaGVtaWNhbCBtb2RlbGluZyBkYXRhPwoKIyMjIwoKIyMjIExlYXJuaW5nIE9iamVjdGl2ZXMgCgpJbiB0aGlzIGNhc2Ugc3R1ZHksIHdlIHdpbGwgd2FsayB5b3UgdGhyb3VnaCBpbXBvcnRpbmcgZGF0YSBmcm9tIENTViBmaWxlcyBhbmQgcGVyZm9ybWluZyBtYWNoaW5lIGxlYXJuaW5nIG1ldGhvZHMgdG8gcHJlZGljdCBvdXIgb3V0Y29tZSB2YXJpYWJsZSBvZiBpbnRlcmVzdCAoaW4gdGhpcyBjYXNlIGFubnVhbCBmaW5lIHBhcnRpY2xlIGFpciBwb2xsdXRpb24gZXN0aW1hdGVzKS4gV2Ugd2lsbCBlc3BlY2lhbGx5IGZvY3VzIG9uIHVzaW5nIHBhY2thZ2VzIGFuZCBmdW5jdGlvbnMgZnJvbSB0aGUgW2BUaWR5dmVyc2VgXShodHRwczovL3d3dy50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSwgYW5kIG1vcmUgc3BlY2lmaWNhbGx5IHRoZSBbYHRpZHltb2RlbHNgXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvdGlkeW1vZGVscy90aWR5bW9kZWxzLnBkZil7dGFyZ2V0PSJfYmxhbmsifSBwYWNrYWdlL2Vjb3N5c3RlbSBwcmltYXJpbHkgZGV2ZWxvcGVkIGFuZCBtYWludGFpbmVkIGJ5IFtNYXggS3Vobl0oaHR0cHM6Ly9yZXNvdXJjZXMucnN0dWRpby5jb20vYXV0aG9ycy9tYXgta3Vobil7dGFyZ2V0PSJfYmxhbmsifSBhbmQgW0RhdmlzIFZhdWdoYW5dKGh0dHBzOi8vcmVzb3VyY2VzLnJzdHVkaW8uY29tL2F1dGhvcnMvZGF2aXMtdmF1Z2hhbil7dGFyZ2V0PSJfYmxhbmsifS4gVGhpcyBwYWNrYWdlIGxvYWRzIG1vcmUgbW9kZWxpbmcgcmVsYXRlZCBwYWNrYWdlcyBsaWtlIGByc2FtcGxlYCwgYHJlY2lwZXNgLCBgcGFyc25pcGAsIGB5YXJkc3RpY2tgLCAgYW5kIGBkaWFsc2AuIFdlIHdpbGwgYWxzbyBicmllZmx5IGNvdmVyIHRoZSBgd29ya2Zsb3dzYCBhbmQgYHR1bmVgIHBhY2thZ2VzLiBUaGUgdGlkeXZlcnNlIGlzIGEgbGlicmFyeSBvZiBwYWNrYWdlcyBjcmVhdGVkIGJ5IFJTdHVkaW8uIFdoaWxlIHNvbWUgc3R1ZGVudHMgbWF5IGJlIGZhbWlsaWFyIHdpdGggcHJldmlvdXMgUiBwcm9ncmFtbWluZyBwYWNrYWdlcywgdGhlc2UgcGFja2FnZXMgbWFrZSBkYXRhIHNjaWVuY2UgaW4gUiBlc3BlY2lhbGx5IGVmZmljaWVudC4KCgpgYGB7ciwgb3V0LndpZHRoID0gIjIwJSIsIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduID0iY2VudGVyIn0KaW5jbHVkZV9ncmFwaGljcygiaHR0cHM6Ly90aWR5dmVyc2UudGlkeXZlcnNlLm9yZy9sb2dvLnBuZyIpCmBgYAoKYGBge3IsIG91dC53aWR0aCA9ICIxMDBweCIsIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduID0iY2VudGVyIn0KaW5jbHVkZV9ncmFwaGljcygiaHR0cHM6Ly9wYnMudHdpbWcuY29tL21lZGlhL0RrQkZwU3NXNEFJeXlJTi5wbmciKQpgYGAKCgpXZSB3aWxsIGJlZ2luIGJ5IGxvYWRpbmcgdGhlIHBhY2thZ2VzIHRoYXQgd2Ugd2lsbCBuZWVkOgoKYGBge3J9CmxpYnJhcnkoaGVyZSkKbGlicmFyeShyZWFkcikKbGlicmFyeShkcGx5cikKbGlicmFyeShza2ltcikKbGlicmFyeShzdW1tYXJ5dG9vbHMpCmxpYnJhcnkobWFncml0dHIpCmxpYnJhcnkoY29ycnBsb3QpCmxpYnJhcnkoZ2djb3JycGxvdCkKbGlicmFyeShHR2FsbHkpCmxpYnJhcnkodGlkeW1vZGVscykjIGJyb29tLCBkaWFscywgaW5mZXIsIHBhcnNuaXAsIHB1cnJyLCByZWNpcGVzLCByc2FtcGxlLCB0aWJibGUsIHlhcmRzdGljawpsaWJyYXJ5KHdvcmtmbG93cykKbGlicmFyeSh0dW5lKQoKCiMgbGlicmFyeShzdHJpbmdyKQojIGxpYnJhcnkocHVycnIpCiMgbGlicmFyeSh0aWJibGUpCiMgbGlicmFyeSh0aWR5cikKIyBsaWJyYXJ5KGdncGxvdDIpCiMgbGlicmFyeShnZ3B1YnIpCiMgbGlicmFyeShmb3JjYXRzKQojIGxpYnJhcnkobG1lclRlc3QpCiMgbGlicmFyeShjYXIpCiMgbGlicmFyeShnZ2lyYXBoKQojIGxpYnJhcnkoZ2dmb3JjZSkKIyBsaWJyYXJ5KHZpcmlkaXMpCiMgbGlicmFyeShjb3dwbG90KQpgYGAKCgogUGFja2FnZSAgIHwgVXNlICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAotLS0tLS0tLS0tIHwtLS0tLS0tLS0tLS0tCltoZXJlXShodHRwczovL2dpdGh1Yi5jb20vamVubnliYy9oZXJlX2hlcmUpe3RhcmdldD0iX2JsYW5rIn0gICAgICAgfCB0byBlYXNpbHkgbG9hZCBhbmQgc2F2ZSBkYXRhCltyZWFkcl0oaHR0cHM6Ly9yZWFkci50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gaW1wb3J0IHRoZSBDU1YgZmlsZSBkYXRhCltkcGx5cl0oaHR0cHM6Ly9kcGx5ci50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gdmlldy9hcnJhbmdlL2ZpbHRlci9zZWxlY3QvY29tcGFyZSBzcGVjaWZpYyBzdWJzZXRzIG9mIHRoZSBkYXRhIApbc2tpbXJdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9za2ltci9pbmRleC5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byBnZXQgYW4gb3ZlcnZpZXcgb2YgZGF0YQpbc3VtbWFyeXRvb2xzXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvc2tpbXIvaW5kZXguaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gZ2V0IGFuIG92ZXJ2aWV3IG9mIGRhdGEgaW4gYSBkaWZmZXJlbnQgc3R5bGUKW21hZ3JpdHRyXShodHRwczovL21hZ3JpdHRyLnRpZHl2ZXJzZS5vcmcvYXJ0aWNsZXMvbWFncml0dHIuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgIHwgdG8gdXNlIHRoZSBgJTw+JWAgcGlwcGluZyBvcGVyYXRvciAKW2NvcnJwbG90XShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvY29ycnBsb3QvdmlnbmV0dGVzL2NvcnJwbG90LWludHJvLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBtYWtlIGxhcmdlIGNvcnJlbGF0aW9uIHBsb3RzCltnZ2NvcnJwbG90XShodHRwOi8vd3d3LnN0aGRhLmNvbS9lbmdsaXNoL3dpa2kvZ2djb3JycGxvdC12aXN1YWxpemF0aW9uLW9mLWEtY29ycmVsYXRpb24tbWF0cml4LXVzaW5nLWdncGxvdDIpfCBhbHNvIHRvIG1ha2UgbGFyZ2UgY29ycmVsYXRpb24gcGxvdHMKW0dHYWxseV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL0dHYWxseS9HR2FsbHkucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gbWFrZSBzbWFsbGVyIGNvcnJlbGF0aW9uIHBsb3RzICAKW3JzYW1wbGVdKGh0dHBzOi8vdGlkeW1vZGVscy5naXRodWIuaW8vcnNhbXBsZS9hcnRpY2xlcy9CYXNpY3MuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgIHwgdG8gc3BsaXQgdGhlIGRhdGEgaW50byB0ZXN0aW5nIGFuZCB0cmFpbmluZyBzZXRzIGFuZCB0byBzcGxpdCB0aGUgdHJhaW5pbmcgc2V0IGZvciBjcm9zcy12YWxpZGF0aW9uICAKW3JlY2lwZXNdKGh0dHBzOi8vdGlkeW1vZGVscy5naXRodWIuaW8vcmVjaXBlcy8pe3RhcmdldD0iX2JsYW5rIn0gICB8IHRvIHByZS1wcm9jZXNzIGRhdGEgZm9yIG1vZGVsaW5nIGluIGEgdGlkeSBhbmQgcmVwcm9kdWNpYmxlIHdheSBhbmQgdG8gZXh0cmFjdCBwcmUtcHJvY2Vzc2VkIGRhdGEgKG1ham9yIGZ1bmN0aW9ucyBhcmUgYHJlY2lwZSgpYCAsIGBwcmVwKClgIGFuZCB2YXJpb3VzIHRyYW5zZm9ybWF0aW9uIGBzdGVwXyooKWAgZnVuY3Rpb25zLCBhcyB3ZWxsIGFzIGBqdWljZSgpYCAtIGV4dHJhY3RzIGZpbmFsIHByZXByb2Nlc3NlZCB0cmFpbmluZyBkYXRhIGFuZCBgYmFrZSgpYCAtIGFwcGxpZXMgcmVjaXBlIHN0ZXBzIHRvIHRlc3RpbmcgZGF0YSkuIFNlZSBbaGVyZV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3JlY2lwZXMvcmVjaXBlcy5wZGYpe3RhcmdldD0iX2JsYW5rIn0gIGZvciBtb3JlIGluZm8uCltwYXJzbmlwXShodHRwczovL3RpZHltb2RlbHMuZ2l0aHViLmlvL3BhcnNuaXAvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgfCBhbiBpbnRlcmZhY2UgdG8gY3JlYXRlIG1vZGVscyAobWFqb3IgZnVuY3Rpb25zIGFyZSAgYGZpdCgpYCwgYHNldF9lbmdpbmUoKWApClt5YXJkc3RpY2tdKGh0dHBzOi8vdGlkeW1vZGVscy5naXRodWIuaW8veWFyZHN0aWNrLyl7dGFyZ2V0PSJfYmxhbmsifSAgIHwgdG8gZXZhbHVhdGUgdGhlIHBlcmZvcm1hbmNlIG9mIG1vZGVscwogCgoKW3N0cmluZ3JdKGh0dHBzOi8vc3RyaW5nci50aWR5dmVyc2Uub3JnL2FydGljbGVzL3N0cmluZ3IuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgICB8IHRvIG1hbmlwdWxhdGUgdGhlIHRleHQgd2l0aGluIHRoZSBQREYgb2YgdGhlIGRhdGEKCltwdXJycl0oaHR0cHM6Ly9wdXJyci50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gcGVyZm9ybSBmdW5jdGlvbnMgb24gYWxsIGNvbHVtbnMgb2YgYSB0aWJibGUKW3RpYmJsZV0oaHR0cHM6Ly90aWJibGUudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgIHwgdG8gY3JlYXRlIGRhdGEgb2JqZWN0cyB0aGF0IHdlIGNhbiBtYW5pcHVsYXRlIHdpdGggZHBseXIvc3RyaW5nci90aWR5ci9wdXJycgpbdGlkeXJdKGh0dHBzOi8vdGlkeXIudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIHNlcGFyYXRlIGRhdGEgd2l0aGluIGEgY29sdW1uIGludG8gbXVsdGlwbGUgY29sdW1ucwpbZ2dwbG90Ml0oaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgIHwgdG8gbWFrZSB2aXN1YWxpemF0aW9ucyB3aXRoIG11bHRpcGxlIGxheWVycwpbZ2dwdWJyXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvZ2dwdWJyL2luZGV4Lmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gICAgfCB0byBlYXNpbHkgYWRkIHJlZ3Jlc3Npb24gbGluZSBlcXVhdGlvbnMgdG8gcGxvdHMKW2ZvcmNhdHNdKGh0dHBzOi8vZm9yY2F0cy50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICB8IHRvIGNoYW5nZSBkZXRhaWxzIGFib3V0IGZhY3RvcnMgKGNhdGVnb3JpY2FsIHZhcmlhYmxlcykKW2xtZXJUZXN0XShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvbG1lclRlc3QvbG1lclRlc3QucGRmKXwgdG8gcGVyZm9ybSBsaW5lYXIgbWl4ZWQgbW9kZWwgdGVzdGluZwpbY2FyXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvY2FyL2Nhci5wZGYpfCB0byBwZXJmb3JtIExldmVuZSdzIFRlc3Qgb2YgSG9tb2dlbmVpdHkgb2YgVmFyaWFuY2VzCltnZ2lyYXBoXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvZ2dpcmFwaC9pbmRleC5odG1sKXwgdG8gbWFrZSBwbG90cyBpbnRlcmFjdGl2ZQpbZ2dmb3JjZV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2dnZm9yY2UvZ2dmb3JjZS5wZGYpfCB0byBtb2RpZnkgZmFjZXRzIGluIHBsb3RzClt2aXJpZGlzXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvdmlyaWRpcy92aWduZXR0ZXMvaW50cm8tdG8tdmlyaWRpcy5odG1sKXwgdG8gcGxvdCBpbiBjb2xvciBwYWxldHRlIHRoYXQgaXMgZWFzaWx5IGludGVycHJldGVkIGJ5IGNvbG9yYmxpbmQgaW5kaXZpZHVhbHMKW2Nvd3Bsb3RdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9jb3dwbG90L3ZpZ25ldHRlcy9pbnRyb2R1Y3Rpb24uaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIGFsbG93IHBsb3RzIHRvIGJlIGNvbWJpbmVkCl9fXwoKCgpUaGUgZmlyc3QgdGltZSB3ZSB1c2UgYSBmdW5jdGlvbiwgd2Ugd2lsbCB1c2UgdGhlIGA6OmAgdG8gaW5kaWNhdGUgd2hpY2ggcGFja2FnZSB3ZSBhcmUgdXNpbmcuIFVubGVzcyB3ZSBoYXZlIG92ZXJsYXBwaW5nIGZ1bmN0aW9uIG5hbWVzLCB0aGlzIGlzIG5vdCBuZWNlc3NhcnksIGJ1dCB3ZSB3aWxsIGluY2x1ZGUgaXQgaGVyZSB0byBiZSBpbmZvcm1hdGl2ZSBhYm91dCB3aGVyZSB0aGUgZnVuY3Rpb25zIHdlIHdpbGwgdXNlIGNvbWUgZnJvbS4KCgojIyMgQ29udGV4dAoKVGhlIFtTdGF0ZSBvZiBHbG9iYWwgQWlyXShodHRwczovL3d3dy5zdGF0ZW9mZ2xvYmFsYWlyLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gaXMgYSByZXBvcnQgcmVsZWFzZWQgZXZlcnkgeWVhciB0byBjb21tdW5pY2F0ZSB0aGUgaW1wYWN0IG9mIGFpciBwb2xsdXRpb24gb24gcHVibGljIGhlYWx0aC4gCgpUaGUgW1N0YXRlIG9mIEdsb2JhbCBBaXIgMjAxOSByZXBvcnRdKGh0dHBzOi8vd3d3LnN0YXRlb2ZnbG9iYWxhaXIub3JnL3NpdGVzL2RlZmF1bHQvZmlsZXMvc29nYV8yMDE5X3JlcG9ydC5wZGYpe3RhcmdldD0iX2JsYW5rIn0Kd2hpY2ggdXNlcyBkYXRhIGZyb20gMjAxNyBzdGF0ZWQgdGhhdDoKCj4gQWlyIHBvbGx1dGlvbiBpcyB0aGUgKipmaWZ0aCoqIGxlYWRpbmcgcmlzayBmYWN0b3IgZm9yIG1vcnRhbGl0eSB3b3JsZHdpZGUuIEl0IGlzIHJlc3BvbnNpYmxlIGZvciBtb3JlCmRlYXRocyB0aGFuIG1hbnkgYmV0dGVyLWtub3duIHJpc2sgZmFjdG9ycyBzdWNoIGFzIG1hbG51dHJpdGlvbiwgYWxjb2hvbCB1c2UsIGFuZCBwaHlzaWNhbCBpbmFjdGl2aXR5LgpFYWNoIHllYXIsICoqbW9yZSoqIHBlb3BsZSBkaWUgZnJvbSBhaXIgcG9sbHV0aW9u4oCTcmVsYXRlZCBkaXNlYXNlIHRoYW4gZnJvbSByb2FkICoqdHJhZmZpYyBpbmp1cmllcyoqIG9yICoqbWFsYXJpYSoqLgoKPHAgYWxpZ249ImNlbnRlciI+CiAgPGltZyB3aWR0aD0iNjAwIiBzcmM9Imh0dHBzOi8vd3d3LmhlYWx0aGVmZmVjdHMub3JnL3NpdGVzL2RlZmF1bHQvZmlsZXMvU29HQS1GaWd1cmVzLTAxLmpwZyI+CjwvcD4KClRoZSByZXBvcnQgYWxzbyBzdGF0ZWQgdGhhdDoKCj5JbiAyMDE3LCBhaXIgcG9sbHV0aW9uIGlzIGVzdGltYXRlZCB0byBoYXZlIGNvbnRyaWJ1dGVkIHRvIGNsb3NlIHRvIDUgbWlsbGlvbgpkZWF0aHMgZ2xvYmFsbHkg4oCUIG5lYXJseSAqKjEgaW4gZXZlcnkgMTAgZGVhdGhzKiouCgpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQud2lkdGg9IjgwMHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwiMjAxN2RlYXRocy5wbmciKSkKYGBgCiMjIyMjIFtbc291cmNlXV0oaHR0cHM6Ly93d3cuc3RhdGVvZmdsb2JhbGFpci5vcmcvc2l0ZXMvZGVmYXVsdC9maWxlcy9zb2dhXzIwMTlfZmFjdF9zaGVldC5wZGYpCgpUaGUgW1N0YXRlIG9mIEdsb2JhbCBBaXIgMjAxOCByZXBvcnRdKGh0dHBzOi8vd3d3LnN0YXRlb2ZnbG9iYWxhaXIub3JnL3NpdGVzL2RlZmF1bHQvZmlsZXMvc29nYS0yMDE4LXJlcG9ydC5wZGYpe3RhcmdldD0iX2JsYW5rIn0gIHVzaW5nIGRhdGEgZnJvbSAyMDE2IHdoaWNoIHNlcGFyYXRlZCBkaWZmZXJlbnQgdHlwZXMgb2YgYWlyIHBvbGx1dGlvbiwgZm91bmQgdGhhdCAqKnBhcnRpY3VsYXRlIHBvbGx1dGlvbiB3YXMgcGFydGljdWxhcmx5IGFzc29jaWF0ZWQgd2l0aCBtb3J0YWxpdHkqKi4KCmBgYHtyLCBlY2hvID0gRkFMU0UsIG91dC53aWR0aD0iODAwcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCIyMDE3bW9ydGFsaXR5LnBuZyIpKQpgYGAKClRoZSAyMDE5IHJlcG9ydCBzaG93cyB0aGF0IHRoZSBoaWdoZXN0IGxldmVscyBvZiBmaW5lIHBhcnRpY3VsYXRlIHBvbGx1dGlvbiBvY2N1cnMgaW4gQWZyaWNhIGFuZCBBc2lhIGFuZCB0aGF0OgoKPiBNb3JlIHRoYW4gKio5MCUqKiBvZiBwZW9wbGUgd29ybGR3aWRlIGxpdmUgaW4gYXJlYXMgKipleGNlZWRpbmcqKiB0aGUgV29ybGQgSGVhbHRoIE9yZ2FuaXphdGlvbiAoV0hPKSAqKkd1aWRlbGluZSoqIGZvciBoZWFsdGh5IGFpci4gTW9yZSB0aGFuIGhhbGYgbGl2ZSBpbiBhcmVhcyB0aGF0IGRvIG5vdCBldmVuIG1lZXQgV0hP4oCZcyBsZWFzdC1zdHJpbmdlbnQgYWlyIHF1YWxpdHkgdGFyZ2V0LgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoPSI4MDBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsIlBNd29ybGQucG5nIikpCmBgYAoKTG9va2luZyBhdCB0aGUgVVMgc3BlY2lmaWNhbGx5LCBhaXIgcG9sbHV0aW9uIGxldmVscyBhcmUgZ2VuZXJhbGx5IGltcHJvdmluZy4gVGhlIFVTIEVudmlyb25tZW50YWwgUHJvdGVjdGlvbiBBZ2VuY3kgKEVQQSkgYWxzbyByZWxlYXNlcyBhIHJlcG9ydCBhYm91dCBhaXIgcG9sbHV0aW9uIGxldmVscyBjYWxsZWQgWypPdXIgTmF0aW9uJ3MgQWlyKl0oaHR0cHM6Ly9naXNwdWIuZXBhLmdvdi9haXIvdHJlbmRzcmVwb3J0LzIwMTkvI2hvbWUpe3RhcmdldD0iX2JsYW5rIn0uCgpgYGB7ciwgZWNobyA9IEZBTFNFfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAiVVMucG5nIikpCmBgYAoKIyMjIyMgW1tzb3VyY2VdXShodHRwczovL2dpc3B1Yi5lcGEuZ292L2Fpci90cmVuZHNyZXBvcnQvMjAxOS9kb2N1bWVudGF0aW9uL0FpclRyZW5kc19GbHllci5wZGYpCgpIb3dldmVyLCBhaXIgcG9sbHV0aW9uICoqY29udGludWVzIHRvIGNvbnRyaWJ1dGUgdG8gaGVhbHRoIHJpc2sgZm9yIEFtZXJpY2FucyoqLCBpbiBwYXJ0aWN1bGFyIGluICoqcmVnaW9ucyB3aXRoIGhpZ2hlciB0aGFuIG5hdGlvbmFsIGF2ZXJhZ2UgcmF0ZXMqKiBvZiBwb2xsdXRpb24gdGhhdCBhY3R1YWxseSBhdCB0aW1lIGV4Y2VlZCB0aGUgd29ybGQgaGVhbHRoIG9yZ2FuaXphdGlvbidzIHJlY29tbWVuZGVkIGxldmVsLiBUaHVzIGl0IGlzIG5lY2Vzc2FyeSB0byBvYnRhaW4gaGlnaCBzcGF0aWFsIGdyYW51bGFyaXR5IGluIGVzdGltYXRlcyBvZiBhaXIgcG9sbHV0aW9uIGluIG9yZGVyIHRvIGlkZW50aWZ5IGxvY2F0aW9ucyB3aGVyZSBwb3B1bGF0aW9ucyBhcmUgZXhwZXJpZW5jaW5nIGhhcm1mdWwgbGV2ZWxzIG9mIGV4cG9zdXJlLgoKCllvdSBjYW4gc2VlIHRoYXQgY3VycmVudCBhaXIgcXVhbGl0eSBjb25kaXRpb25zIGF0IHRoaXMgW3dlYnNpdGVdKGh0dHBzOi8vYXFpY24ub3JnL2NpdHkvdXNhLyl7dGFyZ2V0PSJfYmxhbmsifSBhbmQgeW91IHdpbGwgbm90aWNlIHZhcmlhdGlvbiBhY3Jvc3MgZGlmZmVyZW50IGNpdGllcy4KCkhlcmUgd2VyZSB0aGUgY29uZGl0aW9ucyBpbiBUb3Bla2EgS2Fuc2FzIHdoZW4gdGhpcyB3YXMgd3JpdHRlbjoKCmBgYHtyLCBlY2hvID0gRkFMU0V9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJLYW5zYXMucG5nIikpCmBgYAoKSXQgcmVwb3J0cyBwYXJ0aWN1bGF0ZSB2YWx1ZXMgdXNpbmcgd2hhdCBpcyBjYWxsZWQgdGhlIFtBaXIgUXVhbGl0eSBJbmRleF0oaHR0cHM6Ly93d3cuYWlybm93Lmdvdi9pbmRleC5jZm0/YWN0aW9uPWFxaWJhc2ljcy5hcWkpe3RhcmdldD0iX2JsYW5rIn0gc2NhbGUgKEFRSSksIHRoaXMgW2NhbGN1bGF0b3JdKGh0dHBzOi8vYWlybm93Lmdvdi9pbmRleC5jZm0/YWN0aW9uPWFpcm5vdy5jYWxjdWxhdG9yKXt0YXJnZXQ9Il9ibGFuayJ9IGluZGljYXRlcyB0aGF0IDExNCBBUUkgaXMgZXF1aXZhbGVudCB0byA0MC43IHVnL21eM14gYW5kIGlzIGNvbnNpZGVyZWQgdW5oZWFsdGh5IGZvciBzZW5zaXRpdmUgaW5kaXZpZHVhbHMuIFRodXMgc29tZSBhcmVhcyB2ZXJ5IG11Y2ggZXhjZWVkIHRoZSBXb3JsZCBIZWFsdGggT3JnYW5pemF0aW9uIChXSE8pICBhbm51YWwgZXhwb3N1cmUgZ3VpZGVsaW5lICgxMCB1Zy9tXjNeKSBhdCBjZXJ0YWluIHRpbWVzIGFuZCB0aGlzIG1heSBhZHZlcnNlbHkgYWZmZWN0IHRoZSBoZWFsdGggb2YgcGVvcGxlIGxpdmluZyBpbiB0aGVzZSBsb2NhdGlvbnMuCgpGdXJ0aGVybW9yZSwgYWR2ZXJzZSBoZWFsdGggZWZmZWN0cyBoYXZlIGJlZW4gYXNzb2NpYXRlZCB3aXRoIHBvcHVsYXRpb25zIGV4cGVyaWVuY2luZyBoaWdoZXIgcG9sbHV0aW9uIGV4cG9zdXJlIGRlc3BpdGUgdGhlIGxldmVscyBiZWluZyBiZWxvdyBzdWdnZXN0ZWQgZ3VpZGVsaW5lcy4gU2Vjb25kbHksIGl0IGFwcGVhcnMgdGhhdCB0aGUgY29tcG9zaXRpb24gb2YgdGhlIHBhcnRpY3VsYXRlIG1hdGVyIGFuZCB0aGUgaW5mbHVlbmNlIG9mIG90aGVyIGRlbW9ncmFwaGljIGZhY3RvcnMgbWF5IG1ha2Ugc3BlY2lmaWMgcG9wdWxhdGlvbnMgbW9yZSBhdCByaXNrIGZvciBhZHZlcnNlIGhlYWx0aCBlZmZlY3RzIGR1ZSB0byBhaXIgcG9sbHV0aW9uLiBTZWUgdGhpcyBbYXJ0aWNsZV0oaHR0cHM6Ly93d3cubmVqbS5vcmcvZG9pL2Z1bGwvMTAuMTA1Ni9ORUpNb2ExNzAyNzQ3KXt0YXJnZXQ9Il9ibGFuayJ9IGZvciBtb3JlIGRldGFpbHMuCgpUaGUgbW9uaXRvciBkYXRhIHRoYXQgd2Ugd2lsbCB1c2UgaW4gdGhpcyBjYXNlIHN0dWR5IGNvbWVzIGZyb20gYSBzeXN0ZW0gb2YgbW9uaXRvcnMgaW4gd2hpY2ggcm91Z2hseSA5MCUgYXJlIGxvY2F0ZWQgd2l0aGluIGNpdGllcy4gVGh1cyB0aGVyZSBpcyBhbiAqKmVxdWl0eSBpc3N1ZSoqIGluIHRlcm1zIG9mIGNhcHR1cmluZyB0aGUgYWlyIHBvbGx1dGlvbiBsZXZlbHMgb2YgbW9yZSBydXJhbCBhcmVhcy4gVGhlcmVmb3JlLCB0byBnZXQgYSBiZXR0ZXIgc2Vuc2Ugb2YgdGhlIHBvbGx1dGlvbiBleHBvc3VyZXMgZm9yIHRoZSBpbmRpdmlkdWFscyBsaXZpbmcgaW4gdGhlc2UgYXJlYXMsIG1ldGhvZHMgbGlrZSBtYWNoaW5lIGxlYXJuaW5nIGNhbiBiZSB2ZXJ5IHVzZWZ1bCB0byBlc3RpbWF0ZSBhaXIgcG9sbHV0aW9uIGxldmVscyBpbiAqKmFyZWFzIHdpdGggbGl0dGxlIHRvIG5vIG1vbml0b3JpbmcqKi4KCkluZGVlZCwgbWFjaGluZSBsZWFybmluZyBtZXRob2RzIGFyZSBpbiBmYWN0IHVzZWQgdG8gYmUgYWJsZSB0byBlc3RpbWF0ZSBhaXIgcG9sbHV0aW9uIGluIHRoZXNlIGxvdyBtb25pdG9yaW5nIGFyZWFzIHNvIHRoYXQgd2UgY2FuIG1ha2UgYSBtYXAgbGlrZSB0aGlzIHdoZXJlIHdlIGhhdmUgYW5udWFsIGVzdGltYXRlcyBmb3IgYWxsIG9mIHRoZSBjb250aWd1b3VzIFVTOgoKPHAgYWxpZ249ImNlbnRlciI+CiAgPGltZyB3aWR0aD0iNjAwIiBzcmM9Imh0dHBzOi8vYXJjLWFuZ2xlcmZpc2gtd2FzaHBvc3QtcHJvZC13YXNocG9zdC5zMy5hbWF6b25hd3MuY29tL3B1YmxpYy9TQVdPRUdCWE1WR1E3QVM1UFo2VVVPWDZGWS5wbmciPgo8L3A+CgoKIyMjIyMgW1tzb3VyY2VdXShodHRwczovL3d3dy5nb29nbGUuY29tL3VybD9zYT1pJnVybD1odHRwcyUzQSUyRiUyRnd3dy53YXNoaW5ndG9ucG9zdC5jb20lMkZidXNpbmVzcyUyRjIwMTklMkYxMCUyRjIzJTJGYWlyLXBvbGx1dGlvbi1pcy1nZXR0aW5nLXdvcnNlLWRhdGEtc2hvdy1tb3JlLXBlb3BsZS1hcmUtZHlpbmclMkYmcHNpZz1BT3ZWYXczdi1aRFRCUG5MUDJNWXRLZjNVbmRqJnVzdD0xNTg1Nzg0NDc5MDY4MDAwJnNvdXJjZT1pbWFnZXMmY2Q9dmZlJnZlZD0wQ0FJUWpSeHFGd29UQ1BDeW45Znh4ZWdDRlFBQUFBQWRBQUFBQUJBZCkKClRoaXMgaXMgd2hhdCB3ZSBhaW0gdG8gYWNoaWV2ZSBpbiB0aGlzIGNhc2Ugc3R1ZHkuCgojIyMgTGltaXRhdGlvbnMKClRoZXJlIGFyZSBzb21lIGltcG9ydGFudCBjb25zaWRlcmF0aW9ucyByZWdhcmRpbmcgdGhpcyBkYXRhIGFuYWx5c2lzIHRvIGtlZXAgaW4gbWluZDogCgoxKSBUaGUgZGF0YSBpbiBvdXIgYW5hbHlzaXMgZG9lcyBub3QgaW5jbHVkZSBpbmZvcm1hdGlvbiBhYm91dCB0aGUgY29tcG9zaXRpb24gb2YgcGFydGljdWxhdGUgbWF0ZXIuIERpZmZlcmVudCB0eXBlcyBvZiBwYXJ0aWN1bGF0ZXMgbWF5IGJlIG1vcmUgYmVuaWduIG9yIGRlbGV0ZXJpb3VzIGZvciBoZWFsdGggb3V0Y29tZXMuCgoyKSBPdXRkb29yIHBvbGx1dGlvbiBsZXZlbHMgYXJlIG5vdCBuZWNlc3NhcmlseSBhbiBpbmRpY2F0aW9uIG9mIG9mIGluZGl2aWR1YWwgZXhwb3N1cmVzLiBQZW9wbGUgc3BlbmQgZGlmZmVyaW5nIGFtb3VudHMgb2YgdGltZSBpbmRvb3JzIGFuZCBvdXRkb29ycyBhbmQgYXJlIGV4cG9zZWQgdG8gZGlmZmVyZW50IHBvbGx1dGlvbiBsZXZlbHMgaW5kb29ycy4gUGVvcGxlIGFyZSBub3cgZGV2ZWxvcGluZyBwZXJzb25hbCBtb25pdG9yaW5nIHN5c3RlbXMgdG8gdHJhY2sgYWlyIHBvbGx1dGlvbiBsZXZlbHMgb24gdGhlIHBlcnNvbmFsIGxldmVsLgoKT3VyIGFuYWx5c2lzIHdpbGwgdXNlIGFubnVhbCBtZWFuIGVzdGltYXRlcywgaG93ZXZlciBwb2xsdXRpb24gbGV2ZWxzIGNhbiB2YXJ5IGdyZWF0bHkgYnkgc2Vhc29uLCBkYXkgYW5kIGV2ZW4gaG91ci4gVGhlcmUgYXJlIGRhdGEgc291cmNlcyB0aGF0IGhhdmUgZmluZXIgbGV2ZWxzIG9mIHRlbXBvcmFsIGRhdGEsIGhvd2V2ZXIgd2UgYXJlIGludGVyZXN0ZWQgaW4gbG9uZyB0ZXJtIGV4cG9zdXJlcywgYXMgdGhlc2UgYXBwZWFyIHRvIGJlIHRoZSBtb3N0IGluZmx1ZW50aWFsIGZvciBoZWFsdGggb3V0Y29tZXMsIHNvIHdlIGNob3NlIHRvIHVzZSBhbm51YWwgbGV2ZWwgZGF0YS4gCgoKIyMgV2hhdCBhcmUgdGhlIGRhdGE/CgpJbiBNYWNoaW5lIExlYXJuaW5nIGZvciBwcmVkaWN0aW9uLCB0aGVyZSBhcmUgdHdvIG1haW4gdHlwZXMgb2YgdmFyaWFibGVzOgoKMSkgT3V0Y29tZSB2YXJpYWJsZQoyKSBQcmVkaWN0b3IgdmFyaWFibGVzCgpUaGUgKipvdXRjb21lIHZhcmlhYmxlKiogaXMgd2hhdCBhcmUgdHJ5aW5nIHRvICoqcHJlZGljdCoqLiBJbiBidWlsZGluZyBvdXIgbW9kZWwgd2UgYWN0dWFsbHkgaGF2ZSB0aGUgb3V0Y29tZSB2YXJpYWJsZSBkYXRhLCBidXQgd2Ugd2FudCB0byBzZWUgaG93IHdlbGwgb3VyIHByZWRpY3RvciB2YXJpYWJsZXMgY2FuIGV4cGxhaW4gdGhlIHZhcmlhdGlvbiBpbiBvdXIgb3V0Y29tZSBkYXRhLiBUaGlzIGdpdmVzIHVzIGEgc2Vuc2Ugb2YgaG93IHdlbGwgd2UgY2FuIHVzZSB0aGUgcHJlZGljdG9yIHZhcmlhYmxlIGRhdGEgdG8gcHJlZGljdCBvdXIgb3V0Y29tZSB2YXJpYWJsZSBsZXZlbHMgd2hlbiB3ZSBpbiBmYWN0IGRvIG5vdCBoYXZlIGRhdGEgYWJvdXQgdGhlIG91dGNvbWUuCgpBcyBhIHNpbXBsZXIgZXhhbXBsZSwgaW1hZ2luZSB0aGF0IHdlIGhhdmUgZGF0YSBhYm91dCB0aGUgc2FsZXMgYW5kIGNoYXJhY3RlcmlzdGljcyBvZiBjYXJzIGZyb20gbGFzdCB5ZWFyIGFuZCB3ZSB3YW50IHRvIHByZWRpY3Qgd2hpY2ggY2FycyBtaWdodCBzZWxsIHdlbGwgdGhpcyB5ZWFyLiBXZSBkbyBub3QgaGF2ZSB0aGUgc2FsZXMgZGF0YSB5ZXQgZm9yIHRoaXMgeWVhciwgYnV0IHdlIGRvIGtub3cgdGhlIGNoYXJhY3RlcmlzdGljcyBvZiBvdXIgY2FycyBmb3IgdGhpcyB5ZWFyLiBXZSBjYW4gdXNlIGEgbW9kZWwgb2YgdGhlIGNoYXJhY3RlcmlzdGljcyB0aGF0IGV4cGxhaW5lZCBzYWxlcyBsYXN0IHllYXIgdG8gZXN0aW1hdGUgd2hhdCBjYXJzIG1pZ2h0IHNlbGwgd2VsbCB0aGlzIHllYXIuIEluIHRoaXMgY2FzZSwgb3VyIG91dGNvbWUgdmFyaWFibGUgaXMgdGhlIHNhbGUgcGVyZm9ybWFuY2Ugb2YgdGhlIGNhcnMsIHdoaWxlIHRoZSBkaWZmZXJlbnQgY2hhcmFjdGVyaXN0aWNzIG9mIHRoZSBjYXJzIG1ha2UgdXAgb3VyIHByZWRpY3RvciBvciBleHBsYW5hdG9yeSB2YXJpYWJsZXMuCgpJbiB0aGlzIGNhc2Ugc3R1ZHksIHdlIHdpbGwgZXZhbHVhdGUgYWlyIHBvbGx1dGlvbiBtb25pdG9yIGRhdGEgb2YgZmluZSBwYXJ0aWN1bGF0ZSBtYXRlciAoUE1+Mi41fikgaW4gdGhlIGNvbnRpZ3VvdXMgVVMgZnJvbSAyMDA4LCBhcyB3ZWxsIGFzIGRhdGEgYWJvdXQgcG9wdWxhdGlvbiBkZW5zaXR5LCByb2FkIGRlbnNpdHksIHVyYmFuaXphdGlvbiBsZXZlbHMsIGFuZCBOQVNBIHNhdGVsbGl0ZSBkYXRhIHRvIGRldmVsb3AgbW9kZWxzIHRvIHByZWRpY3QgbG9jYWxpemVkIGFpciBwb2xsdXRpb24gbGV2ZWxzLiAKClRoZSBtb25pdG9yIGRhdGEgd2lsbCBiZSBvdXIgKipvdXRjb21lIHZhcmlhYmxlKiouICBXZSB3YW50IHRvIGRldGVybWluZSBpZiB3ZSBjYW4gKipwcmVkaWN0KiogYWlyIHBvbGx1dGlvbiBsZXZlbHMgYmFzZWQgb24gb3RoZXIgdHlwZXMgb2YgZGF0YSwgbGlrZSByb2FkIGRlbnNpdHkgYW5kIHBvcHVsYXRpb24gZGVuc2l0eSB0byBzZWUgaWYgd2UgY2FuIHVzZSB0aGVzZSBkYXRhIHRvIHByZWRpY3QgYWlyIHBvbGx1dGlvbiBpbiBhcmVhcyB3aGVyZSB0aGVyZSBhcmUgbm8gbW9uaXRvcnMuIAoKCiMjIyBPdXIgb3V0Y29tZSB2YXJpYWJsZQoKVGhlIG1vbml0b3IgZGF0YSB0aGF0IHdlIHdpbGwgYmUgdXNpbmcgY29tZXMgZnJvbSAqKltncmF2aW1ldHJpYyBtb25pdG9yc10oaHR0cHM6Ly9wdWJsaWNsYWIub3JnL3dpa2kvZmlsdGVyLXBtKXt0YXJnZXQ9Il9ibGFuayJ9Kiogb3BlcmF0ZWQgYnkgdGhlIFVTIFtFbml2b3JubWVudGFsIFByb3RlY3Rpb24gQWdlbmN5IChFUEEpXShodHRwczovL3d3dy5lcGEuZ292Lyl7dGFyZ2V0PSJfYmxhbmsifS4gVGhlc2UgbW9uaXRvcnMgdXNlIGEgZmlsdHJhdGlvbiBzeXN0ZW0gdG8gc3BlY2lmaWNhbGx5IGNhcHR1cmUgZmluZSBwYXJ0aWN1bGF0ZSBtYXR0ZXIuIFRoZSB3ZWlnaHQgb2YgdGhpcyBtYXR0ZXIgaXMgbWFudWFsbHkgbWVhc3VyZWQgZGFpbHkgb3Igd2Vla2x5LiBTZWUgW2hlcmVdKGh0dHBzOi8vd3d3My5lcGEuZ292L3R0bmFtdGkxL2ZpbGVzL2FtYmllbnQvcG0yNS9zcGVjL1JUSUdyYXZNYXNzU09QRklOQUwucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IGZvciB0aGUgRVBBIHN0YW5kYXJkIG9wZXJhdGluZyBwcm9jZWR1cmUgZm9yIFBNIGdyYXZpbWV0cmljIGFuYWx5c2lzIGluIDIwMDguCgoKCmBgYHtyLCBlY2hvID0gRkFMU0UsIG91dC53aWR0aD0iMTUwcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJmaWx0ZXIucG5nIikpCmBgYAoKIyMjIyMgW1tzb3VyY2VdKGh0dHBzOi8vcHVibGljbGFiLm9yZy93aWtpL2ZpbHRlci1wbSldCgpIZXJlIGlzIGFuIGltYWdlIG9mIHdoYXQgdGhlIGdyYXZpbWV0cmljIG1vbml0b3JzIGxvb2sgbGlrZToKCmBgYHtyLCBlY2hvID0gRkFMU0UsIG91dC53aWR0aD0iMTAwcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJtb25pdG9yLnBuZyIpKQpgYGAKCgpHcmF2aW1ldHJpYyBhbmFseXNpcyBpcyBhbHNvIHVzZWQgZm9yIFtlbWlzc2lvbiB0ZXN0aW5nXShodHRwczovL3d3dy5tdC5jb20vdXMvZW4vaG9tZS9hcHBsaWNhdGlvbnMvTGFib3JhdG9yeV93ZWlnaGluZy9lbWlzc2lvbnMtdGVzdGluZy1wYXJ0aWN1bGF0ZS1tYXR0ZXIuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifS4gVGhlIHNhbWUgaWRlYSBhcHBsaWVzOiBhIGZyZXNoIGZpbHRlciBpcyBhcHBsaWVkIGFuZCB0aGUgZGVzaXJlZCBhbW91bnQgb2YgdGltZSBwYXNzZXMsIHRoZW4gdGhlIGZpbHRlciBpcyByZW1vdmVkIGFuZCB3ZWlnaGVkLiAKClRoZXJlIGFyZSBbb3RoZXIgbW9uaXRvcmluZyBzeXN0ZW1zXShodHRwczovL3d3dy5zZW5zaXJpb24uY29tL2VuL2Fib3V0LXVzL25ld3Nyb29tL3NlbnNpcmlvbi1zcGVjaWFsaXN0LWFydGljbGVzL3BhcnRpY3VsYXRlLW1hdHRlci1zZW5zaW5nLWZvci1haXItcXVhbGl0eS1tZWFzdXJlbWVudHMvKXt0YXJnZXQ9Il9ibGFuayJ9IHRoYXQgY2FuIHByb3ZpZGUgaG91cmx5IG1lYXN1cmVtZW50cywgYnV0IHdlIHdpbGwgbm90IGJlIHVzaW5nIGRhdGEgZnJvbSB0aGVzZSBtb25pdG9ycyBpbiBvdXIgYW5hbHlzaXMuIEdyYXZpbWV0cmljIGFuYWx5c2lzIGlzIGNvbnNpZGVyZWQgdG8gYmUgYW1vbmcgdGhlIG1vc3QgYWNjdXJhdGUgbWV0aG9kcy4KCkluIG91ciBjc3YsIHRoZSAqKnZhbHVlKiogY29sdW1uIGluZGljYXRlcyB0aGUgUE1+Mi41fiBtb25pdG9yIGF2ZXJhZ2UgZm9yIDIwMDggaW4gbWFzcyBvZiBmaW5lIHBhcnRpY2xlcy92b2x1bWUgb2YgYWlyIGZvciA4NzYgZ3JhdmltZXRyaWMgbW9uaXRvcnMuIFRoZSB1bml0cyBhcmUgbWljcm8gZ3JhbXMgb2YgZmluZSBwYXJ0aWN1bGF0ZSBtYXRlciAoUE0pIHRoYXQgaXMgbGVzcyB0aGFuIDIuNSBtaWNyb21ldGVycyBpbiBkaWFtZXRlciBwZXIgY3ViaWMgbWV0ZXIgb2YgYWlyIC0gbWFzcyBjb25jZW50cmF0aW9uICh1Zy9tXjNeKS4gIFJlY2FsbCB0aGUgdGhlIFdITyBleHBvc3VyZSAgZ3VpZGVsaW5lIGlzIDwgMTAgdWcvbV4zXiBvbiBhdmVyYWdlIGFubnVhbGx5IGZvciBQTX4yLjV+LgoKIyMjIE91ciBwcmVkaWN0b3IgdmFyaWFibGVzCgpUaGVyZSBhcmUgNDggcHJlZGljdG9yIHZhcmlhYmxlcyB3aXRoIHZhbHVlcyBmb3IgZWFjaCBvZiB0aGUgODc2IG1vbml0b3JzIGluY2x1ZGVkIGluIG91ciBvdXRjb21lIHZhcmlhYmxlLiBUaGUgZGF0YSBjb21lcyBmcm9tIHRoZSBVUyBbRW5pdm9ybm1lbnRhbCBQcm90ZWN0aW9uIEFnZW5jeSAoRVBBKV0oaHR0cHM6Ly93d3cuZXBhLmdvdi8pe3RhcmdldD0iX2JsYW5rIn0sIHRoZSBbTmF0aW9uYWwgQWVyb25hdXRpY3MgYW5kIFNwYWNlIEFkbWluaXN0cmF0aW9uIChOQVNBKV0oaHR0cHM6Ly93d3cubmFzYS5nb3YvKXt0YXJnZXQ9Il9ibGFuayJ9LCB0aGUgVVMgW0NlbnN1c10oaHR0cHM6Ly93d3cuY2Vuc3VzLmdvdi9hYm91dC93aGF0L2NlbnN1cy1hdC1hLWdsYW5jZS5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9LCBhbmQgdGhlIFtOYXRpb25hbCBDZW50ZXIgZm9yIEhlYWx0aCBTdGF0aXN0aWNzIChOQ0hTKV0oaHR0cHM6Ly93d3cuY2RjLmdvdi9uY2hzL2Fib3V0L2luZGV4Lmh0bSl7dGFyZ2V0PSJfYmxhbmsifS4KClZhcmlhYmxlICAgfCBEZXRhaWxzICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCi0tLS0tLS0tLS0gfC0tLS0tLS0tLS0tLS0KKippZCoqICB8IE1vbml0b3IgbnVtYmVyICA8YnI+IC0tIHRoZSBjb3VudHkgbnVtYmVyIGlzIGluZGljYXRlZCBiZWZvcmUgdGhlIGRlY2ltYWwgPGJyPiAtLSB0aGUgbW9uaXRvciBudW1iZXIgaXMgaW5kaWNhdGVkIGFmdGVyIHRoZSBkZWNpbWFsIDxicj4gICoqRXhhbXBsZSoqOiAxMDczLjAwMjMgIGlzIEplZmZlcnNvbiBjb3VudHkgKDEwNzMpIGFuZCAuMDAyMyBvbmUgb2YgOCBtb25pdG9ycyAKKipmaXBzKiogfCBGZWRlcmFsIGluZm9ybWF0aW9uIHByb2Nlc3Npbmcgc3RhbmRhcmQgbnVtYmVyIGZvciB0aGUgY291bnR5IHdoZXJlIHRoZSBtb25pdG9yIGlzIGxvY2F0ZWQgPGJyPiAtLSA1IGRpZ2l0IGlkIGNvZGUgZm9yIGNvdW50aWVzICh6ZXJvIGlzIG9mdGVuIHRoZSBmaXJzdCB2YWx1ZSBhbmQgc29tZXRpbWVzIGlzIG5vdCBzaG93bikgPGJyPiAtLSB0aGUgZmlyc3QgMiBudW1iZXJzIGluZGljYXRlIHRoZSBzdGF0ZSA8YnI+IC0tIHRoZSBsYXN0IHRocmVlIG51bWJlcnMgaW5kaWNhdGUgdGhlIGNvdW50eSA8YnI+ICAqKkV4YW1wbGUqKjogQWxhYmFtYSdzIHN0YXRlIGNvZGUgaXMgMDEgYmVjYXVzZSBpdCBpcyBmaXJzdCBhbHBoYWJldGljYWxseSA8YnI+IChub3RlOiBBbGFza2EgYW5kIEhhd2FpaSBhcmUgbm90IGluY2x1ZGVkIGJlY2F1c2UgdGhleSBhcmUgbm90IHBhcnQgb2YgdGhlIGNvbnRpZ3VvdXMgVVMpICAKKipMYXQqKiB8IExhdGl0dWRlIG9mIHRoZSBtb25pdG9yIGluIGRlZ3JlZXMgIAoqKkxvbioqIHwgTG9uZ2l0dWRlIG9mIHRoZSBtb25pdG9yIGluIGRlZ3JlZXMgIAoqKnN0YXRlKiogfCBTdGF0ZSB3aGVyZSB0aGUgbW9uaXRvciBpcyBsb2NhdGVkCioqY291bnR5KiogfCBDb3VudHkgd2hlcmUgdGhlIG1vbml0b3IgaXMgbG9jYXRlZAoqKmNpdHkqKiB8IENpdHkgd2hlcmUgdGhlIG1vbml0b3IgaXMgbG9jYXRlZAoqKkNNQVEqKiAgfCBFc3RpbWF0ZWQgdmFsdWVzIG9mIGFpciBwb2xsdXRpb24gZnJvbSBhIGNvbXB1dGF0aW9uYWwgbW9kZWwgY2FsbGVkIFsqKkNvbW11bml0eSBNdWx0aXNjYWxlIEFpciBRdWFsaXR5IChDTUFRKSoqXShodHRwczovL3d3dy5lcGEuZ292L2NtYXEpe3RhcmdldD0iX2JsYW5rIn0gPGJyPiAtLSAgQSBtb25pdG9yaW5nIHN5c3RlbSB0aGF0IHNpbXVsYXRlcyB0aGUgcGh5c2ljcyBvZiB0aGUgYXRtb3NwaGVyZSB1c2luZyBjaGVtaXN0cnkgYW5kIHdlYXRoZXIgZGF0YSB0byBwcmVkaWN0IHRoZSBhaXIgcG9sbHV0aW9uIDxicj4gLS0gKioqRG9lcyBub3QgdXNlIGFueSBvZiB0aGUgUE1+Mi41fiBncmF2aW1ldHJpYyBtb25pdG9yaW5nIGRhdGEuKioqIChUaGVyZSBpcyBhIHZlcnNpb24gdGhhdCBkb2VzIHVzZSB0aGUgZ3JhdmltZXRyaWMgbW9uaXRvcmluZyBkYXRhLCBidXQgbm90IHRoaXMgb25lISkgPGJyPiAtLSBEYXRhIGZyb20gdGhlIEVQQQoqKnpjdGEqKiB8IFtaaXAgQ29kZSBUYWJ1bGF0aW9uIEFyZWFdKGh0dHBzOi8vd3d3Mi5jZW5zdXMuZ292L2dlby9wZGZzL2VkdWNhdGlvbi9icm9jaHVyZXMvWkNUQXMucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IHdoZXJlIHRoZSBtb25pdG9yIGlzIGxvY2F0ZWQgPGJyPiAtLSBQb3N0YWwgWmlwIGNvZGVzIGFyZSBjb252ZXJ0ZWQgaW50byAiZ2VuZXJhbGl6ZWQgYXJlYWwgcmVwcmVzZW50YXRpb25zIiB0aGF0IGFyZSBub24tb3ZlcmxhcHBpbmcgIDxicj4gLS0gRGF0YSBmcm9tIHRoZSAyMDEwIENlbnN1cyAgCioqemN0YV9hcmVhKiogfCBMYW5kIGFyZWEgb2YgdGhlIHppcCBjb2RlIGFyZWEgaW4gbWV0ZXJzIHNxdWFyZWQgIDxicj4gLS0gRGF0YSBmcm9tIHRoZSAyMDEwIENlbnN1cyAgCioqemN0YV9wb3AqKiB8IFBvcHVsYXRpb24gaW4gdGhlIHppcCBjb2RlIGFyZWEgIDxicj4gLS0gRGF0YSBmcm9tIHRoZSAyMDEwIENlbnN1cyAgCioqaW1wX2E1MDAqKiB8IEltcGVydmlvdXMgc3VyZmFjZSBtZWFzdXJlIDxicj4gLS0gV2l0aGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgNTAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3IgPGJyPiAtLSBJbXBlcnZpb3VzIHN1cmZhY2UgYXJlIHJvYWRzLCBjb25jcmV0ZSwgcGFya2luZyBsb3RzLCBidWlsZGluZ3MgPGJyPiAtLSBUaGlzIGlzIGEgbWVhc3VyZSBvZiBkZXZlbG9wbWVudCAKKippbXBfYTEwMDAqKiB8IEltcGVydmlvdXMgc3VyZmFjZSBtZWFzdXJlIDxicj4gLS0gIFdpdGhpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDEwMDAgbWV0ZXJzIGFyb3VuZCB0aGUgbW9uaXRvcgoqKmltcF9hNTAwMCoqIHwgSW1wZXJ2aW91cyBzdXJmYWNlIG1lYXN1cmUgPGJyPiAtLSAgV2l0aGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgNTAwMCBtZXRlcnMgYXJvdW5kIHRoZSBtb25pdG9yICAKKippbXBfYTEwMDAwKiogfCBJbXBlcnZpb3VzIHN1cmZhY2UgbWVhc3VyZSA8YnI+IC0tICBXaXRoaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAxMDAwMCBtZXRlcnMgYXJvdW5kIHRoZSBtb25pdG9yICAgCioqaW1wX2ExNTAwMCoqIHwgSW1wZXJ2aW91cyBzdXJmYWNlIG1lYXN1cmUgPGJyPiAtLSAgV2l0aGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgMTUwMDAgbWV0ZXJzIGFyb3VuZCB0aGUgbW9uaXRvciAgCioqY291bnR5X2FyZWEqKiB8IExhbmQgYXJlYSBvZiB0aGUgY291bnR5IG9mIHRoZSBtb25pdG9yIGluIG1ldGVycyBzcXVhcmVkICAKKipjb3VudHlfcG9wKiogfCBQb3B1bGF0aW9uIG9mIHRoZSBjb3VudHkgb2YgdGhlIG1vbml0b3IgIAoqKkxvZ19kaXN0X3RvX3ByaXNlYyoqIHwgTG9nIChOYXR1cmFsIGxvZykgZGlzdGFuY2UgdG8gYSBwcmltYXJ5IG9yIHNlY29uZGFyeSByb2FkIGZyb20gdGhlIG1vbml0b3IgPGJyPiAtLSBIaWdod2F5IG9yIG1ham9yIHJvYWQgIAoqKmxvZ19wcmlfbGVuZ3RoXzUwMDAqKiB8IENvdW50IG9mIHByaW1hcnkgcm9hZCBsZW5ndGggaW4gbWV0ZXJzIGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgNTAwMCBtZXRlcnMgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgPGJyPiAtLSBIaWdod2F5cyBvbmx5ICAKKipsb2dfcHJpX2xlbmd0aF8xMDAwMCoqIHwgQ291bnQgb2YgcHJpbWFyeSByb2FkIGxlbmd0aCBpbiBtZXRlcnMgaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAxMDAwMCBtZXRlcnMgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgPGJyPiAtLSBIaWdod2F5cyBvbmx5ICAKKipsb2dfcHJpX2xlbmd0aF8xNTAwMCoqIHwgQ291bnQgb2YgcHJpbWFyeSByb2FkIGxlbmd0aCBpbiBtZXRlcnMgaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAxNTAwMCBtZXRlcnMgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgPGJyPiAtLSBIaWdod2F5cyBvbmx5ICAKKipsb2dfcHJpX2xlbmd0aF8yNTAwMCoqIHwgQ291bnQgb2YgcHJpbWFyeSByb2FkIGxlbmd0aCBpbiBtZXRlcnMgaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAyNTAwMCBtZXRlcnMgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgPGJyPiAtLSBIaWdod2F5cyBvbmx5ICAKKipsb2dfcHJpc2VjX2xlbmd0aF81MDAqKiB8IENvdW50IG9mIHByaW1hcnkgYW5kIHNlY29uZGFyeSByb2FkIGxlbmd0aCBpbiBtZXRlcnMgaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiA1MDAgbWV0ZXJzIGFyb3VuZCB0aGUgbW9uaXRvciAoTmF0dXJhbCBsb2cpICA8YnI+IC0tIEhpZ2h3YXkgYW5kIHNlY29uZGFyeSByb2FkcyAgCioqbG9nX3ByaXNlY19sZW5ndGhfMTAwMCoqIHwgQ291bnQgb2YgcHJpbWFyeSBhbmQgc2Vjb25kYXJ5IHJvYWQgbGVuZ3RoIGluIG1ldGVycyBpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDEwMDAgbWV0ZXJzIGFyb3VuZCB0aGUgbW9uaXRvciAoTmF0dXJhbCBsb2cpICA8YnI+IC0tIEhpZ2h3YXkgYW5kIHNlY29uZGFyeSByb2FkcyAgCioqbG9nX3ByaXNlY19sZW5ndGhfNTAwMCoqIHwgQ291bnQgb2YgcHJpbWFyeSBhbmQgc2Vjb25kYXJ5IHJvYWQgbGVuZ3RoIGluIG1ldGVycyBpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDUwMDAgbWV0ZXJzIGFyb3VuZCB0aGUgbW9uaXRvciAoTmF0dXJhbCBsb2cpICA8YnI+IC0tIEhpZ2h3YXkgYW5kIHNlY29uZGFyeSByb2FkcyAgCioqbG9nX3ByaXNlY19sZW5ndGhfMTAwMDAqKiB8IENvdW50IG9mIHByaW1hcnkgYW5kIHNlY29uZGFyeSByb2FkIGxlbmd0aCBpbiBtZXRlcnMgaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAxMDAwMCBtZXRlcnMgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgIDxicj4gLS0gSGlnaHdheSBhbmQgc2Vjb25kYXJ5IHJvYWRzICAKKipsb2dfcHJpc2VjX2xlbmd0aF8xNTAwMCoqIHwgQ291bnQgb2YgcHJpbWFyeSBhbmQgc2Vjb25kYXJ5IHJvYWQgbGVuZ3RoIGluIG1ldGVycyBpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDE1MDAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSAgPGJyPiAtLSBIaWdod2F5IGFuZCBzZWNvbmRhcnkgcm9hZHMgIAoqKmxvZ19wcmlzZWNfbGVuZ3RoXzI1MDAwKiogfCBDb3VudCBvZiBwcmltYXJ5IGFuZCBzZWNvbmRhcnkgcm9hZCBsZW5ndGggaW4gbWV0ZXJzIGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgMjUwMDAgbWV0ZXJzIGFyb3VuZCB0aGUgbW9uaXRvciAoTmF0dXJhbCBsb2cpICA8YnI+IC0tIEhpZ2h3YXkgYW5kIHNlY29uZGFyeSByb2FkcyAgICAgIAoqKmxvZ19uZWlfMjAwOF9wbTI1X3N1bV8xMDAwMCoqIHwgVG9ucyBvZiBlbWlzc2lvbnMgZnJvbSBtYWpvciBzb3VyY2VzIGRhdGEgYmFzZSAoYW5udWFsIGRhdGEpIHN1bSBvZiBhbGwgc291cmNlcyB3aXRoaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAxMDAwMCBtZXRlcnMgb2YgZGlzdGFuY2UgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgICAgCioqbG9nX25laV8yMDA4X3BtMjVfc3VtXzE1MDAwKiogfCBUb25zIG9mIGVtaXNzaW9ucyBmcm9tIG1ham9yIHNvdXJjZXMgZGF0YSBiYXNlIChhbm51YWwgZGF0YSkgc3VtIG9mIGFsbCBzb3VyY2VzIHdpdGhpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDE1MDAwIG1ldGVycyBvZiBkaXN0YW5jZSBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSAgICAgCioqbG9nX25laV8yMDA4X3BtMjVfc3VtXzI1MDAwKiogfCBUb25zIG9mIGVtaXNzaW9ucyBmcm9tIG1ham9yIHNvdXJjZXMgZGF0YSBiYXNlIChhbm51YWwgZGF0YSkgc3VtIG9mIGFsbCBzb3VyY2VzIHdpdGhpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDI1MDAwIG1ldGVycyBvZiBkaXN0YW5jZSBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSAgICAgCioqbG9nX25laV8yMDA4X3BtMTBfc3VtXzEwMDAwKiogfCBUb25zIG9mIGVtaXNzaW9ucyBmcm9tIG1ham9yIHNvdXJjZXMgZGF0YSBiYXNlIChhbm51YWwgZGF0YSkgc3VtIG9mIGFsbCBzb3VyY2VzIHdpdGhpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDEwMDAwIG1ldGVycyBvZiBkaXN0YW5jZSBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSAgICAgIAoqKmxvZ19uZWlfMjAwOF9wbTEwX3N1bV8xNTAwMCoqfCBUb25zIG9mIGVtaXNzaW9ucyBmcm9tIG1ham9yIHNvdXJjZXMgZGF0YSBiYXNlIChhbm51YWwgZGF0YSkgc3VtIG9mIGFsbCBzb3VyY2VzIHdpdGhpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDE1MDAwIG1ldGVycyBvZiBkaXN0YW5jZSBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSAgICAgIAoqKmxvZ19uZWlfMjAwOF9wbTEwX3N1bV8yNTAwMCoqIHwgVG9ucyBvZiBlbWlzc2lvbnMgZnJvbSBtYWpvciBzb3VyY2VzIGRhdGEgYmFzZSAoYW5udWFsIGRhdGEpIHN1bSBvZiBhbGwgc291cmNlcyB3aXRoaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAyNTAwMCBtZXRlcnMgb2YgZGlzdGFuY2UgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgICAgICAKKipwb3BkZW5zX2NvdW50eSoqIHwgUG9wdWxhdGlvbiBkZW5zaXR5IChudW1iZXIgb2YgcGVvcGxlIHBlciBraWxvbWV0ZXIgc3F1YXJlZCBhcmVhIG9mIHRoZSBjb3VudHkpCioqcG9wZGVuc196Y3RhKiogfCBQb3B1bGF0aW9uIGRlbnNpdHkgKG51bWJlciBvZiBwZW9wbGUgcGVyIGtpbG9tZXRlciBzcXVhcmVkIGFyZWEgb2YgemN0YSkKKipub2hzKiogfCBQZXJjZW50YWdlIG9mIHBlb3BsZSBpbiB6Y3RhIGFyZWEgd2hlcmUgdGhlIG1vbml0b3IgaXMgdGhhdCAqKmRvIG5vdCBoYXZlIGEgaGlnaCBzY2hvb2wgZGVncmVlKiogPGJyPiAtLSBEYXRhIGZyb20gdGhlIENlbnN1cwoqKnNvbWVocyoqIHwgUGVyY2VudGFnZSBvZiBwZW9wbGUgaW4gemN0YSBhcmVhIHdoZXJlIHRoZSBtb25pdG9yIHdob3NlIGhpZ2hlc3QgZm9ybWFsIGVkdWNhdGlvbmFsIGF0dGFpbm1lbnQgd2FzICoqc29tZSBoaWdoIHNjaG9vbCBlZHVjYXRpb24qKiA8YnI+IC0tIERhdGEgZnJvbSB0aGUgQ2Vuc3VzCioqaHMqKiB8IFBlcmNlbnRhZ2Ugb2YgcGVvcGxlIGluIHpjdGEgYXJlYSB3aGVyZSB0aGUgbW9uaXRvciB3aG9zZSBoaWdoZXN0IGZvcm1hbCBlZHVjYXRpb25hbCBhdHRhaW5tZW50IHdhcyBjb21wbGV0aW5nIGEgKipoaWdoIHNjaG9vbCBkZWdyZWUqKiA8YnI+IC0tIERhdGEgZnJvbSB0aGUgQ2Vuc3VzICAKKipzb21lY29sbGVnZSoqIHwgUGVyY2VudGFnZSBvZiBwZW9wbGUgaW4gemN0YSBhcmVhIHdoZXJlIHRoZSBtb25pdG9yIHdob3NlIGhpZ2hlc3QgZm9ybWFsIGVkdWNhdGlvbmFsIGF0dGFpbm1lbnQgd2FzIGNvbXBsZXRpbmcgKipzb21lIGNvbGxlZ2UgZWR1Y2F0aW9uKiogPGJyPiAtLSBEYXRhIGZyb20gdGhlIENlbnN1cyAKKiphc3NvY2lhdGUqKiB8IFBlcmNlbnRhZ2Ugb2YgcGVvcGxlIGluIHpjdGEgYXJlYSB3aGVyZSB0aGUgbW9uaXRvciB3aG9zZSBoaWdoZXN0IGZvcm1hbCBlZHVjYXRpb25hbCBhdHRhaW5tZW50IHdhcyBjb21wbGV0aW5nIGFuICoqYXNzb2NpYXRlIGRlZ3JlZSoqIDxicj4gLS0gRGF0YSBmcm9tIHRoZSBDZW5zdXMgCioqYmFjaGVsb3IqKiB8IFBlcmNlbnRhZ2Ugb2YgcGVvcGxlIGluIHpjdGEgYXJlYSB3aGVyZSB0aGUgbW9uaXRvciB3aG9zZSBoaWdoZXN0IGZvcm1hbCBlZHVjYXRpb25hbCBhdHRhaW5tZW50IHdhcyBhICoqYmFjaGVsb3IncyBkZWdyZWUqKiA8YnI+IC0tIERhdGEgZnJvbSB0aGUgQ2Vuc3VzIAoqKmdyYWQqKiB8IFBlcmNlbnRhZ2Ugb2YgcGVvcGxlIGluIHpjdGEgYXJlYSB3aGVyZSB0aGUgbW9uaXRvciB3aG9zZSBoaWdoZXN0IGZvcm1hbCBlZHVjYXRpb25hbCBhdHRhaW5tZW50IHdhcyBhICoqZ3JhZHVhdGUgZGVncmVlKiogPGJyPiAtLSBEYXRhIGZyb20gdGhlIENlbnN1cyAKKipwb3YqKiB8IFBlcmNlbnRhZ2Ugb2YgcGVvcGxlIGluIHpjdGEgYXJlYSB3aGVyZSB0aGUgbW9uaXRvciBpcyB0aGF0IGxpdmVkIGluIFsqKnBvdmVydHkqKl0oaHR0cHM6Ly9hc3BlLmhocy5nb3YvMjAwOC1oaHMtcG92ZXJ0eS1ndWlkZWxpbmVzKSBpbiAyMDA4IC0gb3Igd291bGQgaXQgaGF2ZSBiZWVuIDIwMDcgZ3VpZGVsaW5lcz8/aHR0cHM6Ly9hc3BlLmhocy5nb3YvMjAwNy1oaHMtcG92ZXJ0eS1ndWlkZWxpbmVzIDxicj4gLS0gRGF0YSBmcm9tIHRoZSBDZW5zdXMgIAoqKmhzX29ybGVzcyoqIHwgIFBlcmNlbnRhZ2Ugb2YgcGVvcGxlIGluIHpjdGEgYXJlYSB3aGVyZSB0aGUgbW9uaXRvciB3aG9zZSBoaWdoZXN0IGZvcm1hbCBlZHVjYXRpb25hbCBhdHRhaW5tZW50IHdhcyBhICoqaGlnaCBzY2hvb2wgZGVncmVlIG9yIGxlc3MqKiAoc3VtIG9mIG5vaHMsIHNvbWVocywgYW5kIGhzKSAgCioqdXJjMjAxMyoqIHwgWzIwMTMgVXJiYW4tcnVyYWwgY2xhc3NpZmljYXRpb25dKGh0dHBzOi8vd3d3LmNkYy5nb3YvbmNocy9kYXRhL3Nlcmllcy9zcl8wMi9zcjAyXzE2Ni5wZGYpe3RhcmdldD0iX2JsYW5rIn0gb2YgdGhlIGNvdW50eSB3aGVyZSB0aGUgbW9uaXRvciBpcyBsb2NhdGVkIDxicj4gLS0gNiBjYXRlZ29yeSB2YXJpYWJsZSAtIDEgaXMgdG90YWxseSB1cmJhbiA2IGlzIGNvbXBsZXRlbHkgcnVyYWwgPGJyPiAgLS0gRGF0YSBmcm9tIHRoZSBOYXRpb25hbCBDZW50ZXIgZm9yIEhlYWx0aCBTdGF0aXN0aWNzXShodHRwczovL3d3dy5jZGMuZ292L25jaHMvaW5kZXguaHRtKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAKKip1cmMyMDA2KiogfCBbMjAwNiBVcmJhbi1ydXJhbCBjbGFzc2lmaWNhdGlvbl0oaHR0cHM6Ly93d3cuY2RjLmdvdi9uY2hzL2RhdGEvc2VyaWVzL3NyXzAyL3NyMDJfMTU0LnBkZil7dGFyZ2V0PSJfYmxhbmsifSBvZiB0aGUgY291bnR5IHdoZXJlIHRoZSBtb25pdG9yIGlzIGxvY2F0ZWQgPGJyPiAtLSA2IGNhdGVnb3J5IHZhcmlhYmxlIC0gMSBpcyB0b3RhbGx5IHVyYmFuIDYgaXMgY29tcGxldGVseSBydXJhbCA8YnI+IC0tIERhdGEgZnJvbSB0aGUgW05hdGlvbmFsIENlbnRlciBmb3IgSGVhbHRoIFN0YXRpc3RpY3NdKGh0dHBzOi8vd3d3LmNkYy5nb3YvbmNocy9pbmRleC5odG0pe3RhcmdldD0iX2JsYW5rIn0gICAgIAoqKmFvZCoqIHwgQWVyb3NvbCBPcHRpY2FsIERlcHRoIG1lYXN1cmVtZW50IGZyb20gYSBOQVNBIHNhdGVsbGl0ZSA8YnI+IC0tIGJhc2VkIG9uIHRoZSBkZWZyYWN0aW9uIG9mIGEgbGFzZXIgPGJyPiAtLSB1c2VkIGFzIGEgcHJveHkgb2YgcGFydGljdWxhdGUgcG9sbHV0aW9uIDxicj4gLS0gdW5pdC1sZXNzIC0gaGlnaGVyIHZhbHVlIGluZGljYXRlcyBtb3JlIHBvbGx1dGlvbiA8YnI+IC0tIERhdGEgZnJvbSBOQVNBICAKCk1hbnkgb2YgdGhlc2UgcHJlZGljdG9yIHZhcmlhYmxlcyBoYXZlIHRvIGRvIHdpdGggdGhlIGNpcmN1bGFyIGFyZWEgYXJvdW5kIHRoZSBtb25pdG9yIGNhbGxlZCB0aGUgImJ1ZmZlciIuIFRoZXNlIGFyZSBpbGx1c3RyYXRlZCBpbiB0aGUgZm9sbG93aW5nIGZpZ3VyZToKCmBgYHtyLCBlY2hvID0gRkFMU0UsIG91dC53aWR0aCA9ICI4MDBweCIsfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAicmVncmVzc2lvbi5wbmciKSkKYGBgCgojIyMjIyBbW3NvdXJjZV0oaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wdWJtZWQvMTUyOTI5MDYpXQoKCgojIyBEYXRhIEltcG9ydAoKV2UgaGF2ZSBvbmUgQ1NWIGZpbGUgdGhhdCBjb250YWlucyBib3RoIG91ciBzaW5nbGUgKipvdXRjb21lIHZhcmlhYmxlKiogYW5kIGFsbCBvZiBvdXIgKipwcmVkaWN0b3IgdmFyaWFibGVzKiouCgpMZXQncyBpbXBvcnQgb3VyIGRhdGEgaW50byBSIG5vdyBzbyB0aGF0IHdlIGNhbiBleHBsb3JlIHRoZSBkYXRhIGZ1cnRoZXIuIFdlIHdpbGwgY2FsbCBvdXIgZGF0YSBvYmplY3QgYHBtYCBmb3IgcGFydGljdWxhdGUgbWF0dGVyLgoKYGBge3J9CnBtIDwtcmVhZHI6OnJlYWRfY3N2KGhlcmUoImRvY3MiLCAicG0yNV9kYXRhLmNzdiIpKQpgYGAKCiMjIERhdGEgRXhwbG9yYXRpb24gYW5kIFdyYW5nbGluZwoKVGhlIGZpcnN0IHN0ZXAgaW4gcGVyZm9ybWluZyBhIG1hY2hpbmUgbGVhcm5pbmcgYW5hbHlzaXMgaXMgdG8gZXhwbG9yZSB0aGUgZGF0YSB0byBiZXR0ZXIgdW5kZXJzdGFuZCB0aGUgdmFyaWFibGVzICBpbmNsdWRlZCBpbiB0aGUgZGF0YSwgYXMgd2UgbWF5IGxlYXJuIGFib3V0IGltcG9ydGFudCBkZXRhaWxzIGFib3V0IHRoZSBkYXRhIHRoYXQgd2Ugc2hvdWxkIGtlZXAgaW4gbWluZCBhcyB3ZSB0cnkgdG8gcHJlZGljdCBvdXIgb3V0Y29tZSB2YXJpYWJsZS4KCkZpcnN0IGxldCdzIGp1c3QgZ2V0IGEgZ2VuZXJhbCBzZW5zZSBvZiBvdXIgZGF0YS4gV2UgY2FuIGRvIHRoYXQgdXNpbmcgdGhlIGBnbGltcHNlKClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UgKGl0IGlzIGFsc28gaW4gdGhlIGB0aWJibGVgIHBhY2thZ2UpLgoKV2Ugd2lsbCBhbHNvIHVzZSB0aGUgYCU+JWAgcGlwZSB3aGljaCBjYW4gYmUgdXNlZCB0byBkZWZpbmUgdGhlIGlucHV0IGZvciBsYXRlciBzZXF1ZW50aWFsIHN0ZXBzLiBUaGlzIHdpbGwgbWFrZSBtb3JlIHNlbnNlIHdoZW4gd2UgaGF2ZSBtdWx0aXBsZSBzZXF1ZW50aWFsIHN0ZXBzIHVzaW5nIHRoZSBzYW1lIGRhdGEgb2JqZWN0LiBUbyB1c2UgdGhlIHBpcGUgbm90YXRpb24gd2UgbmVlZCB0byBpbnN0YWxsIGFuZCBsb2FkIGRwbHlyIGFzIHdlbGwuCgpGb3IgZXhhbXBsZSBoZXJlIHdlIHdpbGwgZmlyc3QgZ3JhYiB0aGUgYHBtYCBkYXRhIG9iamVjdCwgdGhlbiB3ZSB1c2UgdGhlIGBnbGltcHNlKClgIGZ1bmN0aW9uIG9uIGl0IGJhc2VkIG9uIHRoZSBwaXBlIG5vdGF0aW9uLgoKCmBgYHtyfQpwbSAlPiUKICBkcGx5cjo6Z2xpbXBzZSgpCmBgYAoKV2UgY2FuIHNlZSB0aGF0IHRoZXJlIGFyZSA4NzYgbW9uaXRvcnMgYW5kIHRoYXQgd2UgaGF2ZSA1MCB0b3RhbCB2YXJpYWJsZXMgLSBvbmUgb2Ygd2hpY2ggaXMgdGhlIG91dGNvbWUuIEluIHRoaXMgY2FzZSBvdXIgb3V0Y29tZSB2YXJpYWJsZSBpcyBjYWxsZWQgYHZhbHVlYC4gCgpOb3RpY2UgdGhhdCBzb21lIG9mIHRoZSB2YXJpYWJsZXMgdGhhdCB3ZSB3b3VsZCB0aGluayBvZiBhcyBmYWN0b3JzIChjYXRlZ29yaWNhbCkgYXJlIGN1cnJlbnRseSBvZiBjbGFzcyBkb3VibGUgYXMgaW5kaWNhdGVkIGJ5IHRoZSBgPGRibD5gIGp1c3QgdG8gdGhlIHJpZ2h0IG9mIHRoZSBjb2x1bW4gbmFtZXMvdmFyaWFibGUgbmFtZXMgaW4gdGhlIGBnbGltcHNlKClgIG91dHB1dC4gRm9yIGV4YW1wbGUgdGhlIG1vbml0b3IgSUQgKGlkKSwgdGhlIEZlZGVyYWwgSW5mb3JtYXRpb24gUHJvY2Vzc2luZyBTdGFuZGFyZCBudW1iZXIgZm9yIHRoZSBjb3VudHkgd2hlcmUgdGhlIG1vbml0b3Igd2FzIGxvY2F0ZWQgKGZpcHMpLCBhcyB3ZWxsIGFzIHRoZSB6Y3RhCgpMZXQncyBjb252ZXJ0IHRoZXNlIHZhcmlhYmxlcyBpbnRvIGZhY3RvcnMuIFdlIGNhbiBkbyB0aGlzIHVzaW5nIHRoZSBgbXV0YXRlX2F0KClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UgYW5kIHRoZSBgYXMuZmFjdG9yKClgIGJhc2UgZnVuY3Rpb24uIAoKSW4gdGhpcyBjYXNlIHdlIGFyZSBhbHNvIHVzaW5nIHRoZSBtYWdyaXR0ciBhc3NpZ25tZW50IHBpcGUgb3IgZG91YmxlIHBpcGUgdGhhdCBsb29rcyBsaWtlIHRoaXMgYCU8PiVgIG9mIHRoZSBgbWFncml0dHJgIHBhY2thZ2UuIFRoaXMgYWxsb3dzIHVzIHVzZSB0aGUgYHBtYCBkYXRhIGFzIGlucHV0IGJ1dCBhbHNvIHJlYXNzaWduIHRoZSBvdXRwdXQgdG8gdGhlIHNhbWUgZGF0YSBvYmplY3QgbmFtZS4KCmBgYHtyfQpwbSAlPD4lCiAgZHBseXI6Om11dGF0ZV9hdCh2YXJzKGlkLCBmaXBzLCB6Y3RhKSwgYXMuZmFjdG9yKSAKCmdsaW1wc2UocG0pCmBgYAoKR3JlYXQhIE5vdyB3ZSBjYW4gc2VlIHRoYXQgdGhlc2UgdmFyaWFibGVzIGFyZSBub3cgZmFjdG9ycyBhcyBpbmRpY2F0ZWQgYnkgYDxmY3Q+YCBhZnRlciB0aGUgdmFyaWFibGUgbmFtZS4KCiMjIyBQYWNrYWdlcyB0byBnZXQgYSBzZW5zZSBvZiB0aGUgZGF0YQoKVGhlIGBza2ltKClgIGZ1bmN0aW9uIG9mIHRoZSBgc2tpbXJgIHBhY2thZ2UgaXMgYWxzbyByZWFsbHkgaGVscGZ1bCBmb3IgZ2V0dGluZyBhIGdlbmVyYWwgc2Vuc2Ugb2YgeW91ciBkYXRhLgoKYGBge3J9CnNraW0ocG0pCmBgYAoKTm90aWNlIGhvdyB0aGVyZSBpcyBhIGNvbHVtbiBjYWxsZWQgYG5fbWlzc2luZ2AgYWJvdXQgdGhlIG51bWJlciBvZiB2YWx1ZXMgdGhhdCBhcmUgbWlzc2luZy4gSXQgbG9va3MgbGlrZSBvdXIgZGF0YSBpcyB2ZXJ5IGNvbXBsZXRlIGFuZCB3ZSBkbyBub3QgaGF2ZSBhbnkgbWlzc2luZyBkYXRhLiBUaGlzIGlzIGFsc28gaW5kaWNhdGVkIGJ5IHRoZSBgY29tcGxldGVfcmF0ZWAgdmFyaWFibGUsIHdoaWNoIHNob3dzIHRoZSByYXRpbyBvZiBjb21wbGV0ZW5lc3MsIGluIG91ciBjYXNlIGFsbCB2YXJpYWJsZXMgaGF2ZSBhIHZhbHVlIG9mIDEgaW5kaWNhdGluZyB0aGV5IGFyZSBmdWxseSBjb21wbGV0ZS4KClRoZSBgbl91bnFpdWVgIGNvbHVtbiBzaG93cyB1cyB0aGUgbnVtYmVyIG9mIHVuaXF1ZSB2YWx1ZXMgZm9yIGVhY2ggb2Ygb3VyIGNvbHVtbnMuIFdlIGNhbiBzZWUgdGhhdCB0aGVyZSBhcmUgNDkgc3RhdGVzIHJlcHJlc2VudGVkIGluIHRoZSBkYXRhLCBhbmQgd2Uga25vdyB0aGF0IHRoZSBkYXRhIHNob3VsZCBiZSBvZiB0aGUgY29udGlndW91cyBzdGF0ZXMuIExldCdzIHRha2UgYSBsb29rIHRvIHNlZSB3aGljaCBzdGF0ZXMgYXJlIGluY2x1ZGVkOgoKIyMjIyB7LnNjcm9sbGFibGUgfQpgYGB7cn0KIyBTY3JvbGwgdGhyb3VnaCB0aGUgb3V0cHV0IQpwbSAlPiUgCiAgZGlzdGluY3Qoc3RhdGUpICU+JQogIHByaW50KG4gPSAxZTMpCmBgYAojIyMjCgpMb29rcyBsaWtlICJEaXN0cmljdCBvZiBDb2x1bWJpYSIgaXMgYmVpbmcgaW5jbHVkZWQgYXMgYSBzdGF0ZS4gV2UgY2FuIHNlZSB0aGF0IGluZGVlZCBBbGFza2EgYW5kIEhhd2FpaSBhcmUgbm90IGluY2x1ZGVkIGluIHRoZSBkYXRhLgoKSGVyZSBpcyBhbm90aGVyIG1ldGhvZCBvZiBsb29raW5nIGF0IHRoZSBkYXRhIHVzaW5nIHRoZSBgZGZTdW1tYXJ5KClgIGZ1bmN0aW9uIG9mIHRoZSBgc3VtbWFyeXRvb2xzYHBhY2thZ2UuIFdlIG5lZWQgdG8gY29weSBhbmQgcGFzdGUgdGhlIG91dHB1dCBpbnRvIHRoZSBybWFya2Rvd24uCgpgYGB7ciwgZXZhbCA9IEZBTFNFfQpkZlN1bW1hcnkocG0sIHBsYWluLmFzY2lpID0gRkFMU0UsIHN0eWxlID0gImdyaWQiLCAKICAgICAgICAgIGdyYXBoLm1hZ25pZiA9IDAuNDUsICB0bXAuaW1nLmRpciA9ICJ0bXAiKQpgYGAKCioqRGltZW5zaW9uczoqKiA4NzYgeCA1MCAgCioqRHVwbGljYXRlczoqKiAwICAKCistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgTm8gfCBWYXJpYWJsZSAgICAgICAgICAgICAgICAgICAgIHwgU3RhdHMgLyBWYWx1ZXMgICAgICAgICAgICAgICAgICAgICAgICAgICB8IEZyZXFzICglIG9mIFZhbGlkKSAgfCBHcmFwaCAgICAgICAgICAgICAgIHwgVmFsaWQgIHwgTWlzc2luZyB8Cis9PT09Kz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSs9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0rPT09PT09PT09PT09PT09PT09PT09Kz09PT09PT09PT09PT09PT09PT09PSs9PT09PT09PSs9PT09PT09PT0rCnwgMSAgfCBpZFwgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMVwuIDEwMDMuMDAxXCAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAhW10odG1wL2RzMDEwMS5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbZmFjdG9yXSAgICAgICAgICAgICAgICAgICAgIHwgMlwuIDEwMjcuMDAwMVwgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgM1wuIDEwMzMuMTAwMlwgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNFwuIDEwNDkuMTAwM1wgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNVwuIDEwNTUuMDAxXCAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNlwuIDEwNjkuMDAwM1wgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgN1wuIDEwNzMuMDAyM1wgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOFwuIDEwNzMuMTAwNVwgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOVwuIDEwNzMuMTAwOVwgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMTBcLiAxMDczLjEwMVwgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgWyA4NjYgb3RoZXJzIF0gICAgICAgICAgICAgICAgICAgICAgICAgICB8IDg2NiAoOTguOSUpICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMiAgfCB2YWx1ZVwgICAgICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogMTAuOCAoMi42KVwgICAgICAgICAgICAgICAgICB8IDg3NSBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEwMi5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMyA8IDExLjIgPCAyMy4yXCAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAzLjEgKDAuMikgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMyAgfCBmaXBzXCAgICAgICAgICAgICAgICAgICAgICAgIHwgMVwuIDEwMDNcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAhW10odG1wL2RzMDEwMy5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbZmFjdG9yXSAgICAgICAgICAgICAgICAgICAgIHwgMlwuIDEwMjdcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgM1wuIDEwMzNcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNFwuIDEwNDlcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNVwuIDEwNTVcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNlwuIDEwNjlcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgN1wuIDEwNzNcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDggKCAwLjklKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOFwuIDEwODlcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOVwuIDEwOTdcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDIgKCAwLjIlKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMTBcLiAxMTAxXCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgWyA1NTkgb3RoZXJzIF0gICAgICAgICAgICAgICAgICAgICAgICAgICB8IDg1OCAoOTguMCUpICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgNCAgfCBsYXRcICAgICAgICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogMzguNSAoNC42KVwgICAgICAgICAgICAgICAgICB8IDg3NiBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEwNC5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMjUuNSA8IDM5LjMgPCA0OC40XCAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiA2LjYgKDAuMSkgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgNSAgfCBsb25cICAgICAgICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogLTkxLjcgKDE1KVwgICAgICAgICAgICAgICAgICB8IDg3NiBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEwNS5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgLTEyNC4yIDwgLTg3LjUgPCAtNjhcICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAxOC41ICgtMC4yKSAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgNiAgfCBzdGF0ZVwgICAgICAgICAgICAgICAgICAgICAgIHwgMVwuIENhbGlmb3JuaWFcICAgICAgICAgICAgICAgICAgICAgICAgICB8IDg1ICggOS43JSlcICAgICAgICAgfCAhW10odG1wL2RzMDEwNi5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbY2hhcmFjdGVyXSAgICAgICAgICAgICAgICAgIHwgMlwuIE9oaW9cICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDQ0ICggNS4wJSlcICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgM1wuIElsbGlub2lzXCAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDM4ICggNC4zJSlcICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNFwuIEluZGlhbmFcICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDM2ICggNC4xJSlcICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNVwuIE5vcnRoIENhcm9saW5hXCAgICAgICAgICAgICAgICAgICAgICB8IDM1ICggNC4wJSlcICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNlwuIFBlbm5zeWx2YW5pYVwgICAgICAgICAgICAgICAgICAgICAgICB8IDMyICggMy43JSlcICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgN1wuIE1pY2hpZ2FuXCAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDMwICggMy40JSlcICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOFwuIEZsb3JpZGFcICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDI5ICggMy4zJSlcICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOVwuIEdlb3JnaWFcICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDI4ICggMy4yJSlcICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMTBcLiBUZXhhc1wgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDI3ICggMy4xJSlcICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgWyAzOSBvdGhlcnMgXSAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDQ5MiAoNTYuMiUpICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgNyAgfCBjb3VudHlcICAgICAgICAgICAgICAgICAgICAgIHwgMVwuIEplZmZlcnNvblwgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDE4ICggMi4xJSlcICAgICAgICAgfCAhW10odG1wL2RzMDEwNy5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbY2hhcmFjdGVyXSAgICAgICAgICAgICAgICAgIHwgMlwuIENvb2tcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEyICggMS40JSlcICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgM1wuIEhhbWlsdG9uXCAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDExICggMS4zJSlcICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNFwuIExha2VcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDExICggMS4zJSlcICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNVwuIExvcyBBbmdlbGVzXCAgICAgICAgICAgICAgICAgICAgICAgICB8IDEwICggMS4xJSlcICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNlwuIFdheW5lXCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEwICggMS4xJSlcICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgN1wuIFdhc2hpbmd0b25cICAgICAgICAgICAgICAgICAgICAgICAgICB8IDkgKCAxLjAlKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOFwuIEN1eWFob2dhXCAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDcgKCAwLjglKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOVwuIEphY2tzb25cICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDcgKCAwLjglKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMTBcLiBNYWRpc29uXCAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDcgKCAwLjglKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgWyA0NjEgb3RoZXJzIF0gICAgICAgICAgICAgICAgICAgICAgICAgICB8IDc3NCAoODguNCUpICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgOCAgfCBjaXR5XCAgICAgICAgICAgICAgICAgICAgICAgIHwgMVwuIE5vdCBpbiBhIGNpdHlcICAgICAgICAgICAgICAgICAgICAgICB8IDEwMyAoMTEuOCUpXCAgICAgICAgfCAhW10odG1wL2RzMDEwOC5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbY2hhcmFjdGVyXSAgICAgICAgICAgICAgICAgIHwgMlwuIE5ldyBZb3JrXCAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDkgKCAxLjAlKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgM1wuIENsZXZlbGFuZFwgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDYgKCAwLjclKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNFwuIEJhbHRpbW9yZVwgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDUgKCAwLjYlKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNVwuIENoaWNhZ29cICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDUgKCAwLjYlKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNlwuIERldHJvaXRcICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDUgKCAwLjYlKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgN1wuIE1pbHdhdWtlZVwgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDUgKCAwLjYlKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOFwuIE5ldyBIYXZlblwgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDUgKCAwLjYlKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOVwuIFBoaWxhZGVscGhpYVwgICAgICAgICAgICAgICAgICAgICAgICB8IDUgKCAwLjYlKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMTBcLiBTcHJpbmdmaWVsZFwgICAgICAgICAgICAgICAgICAgICAgICB8IDUgKCAwLjYlKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgWyA1OTcgb3RoZXJzIF0gICAgICAgICAgICAgICAgICAgICAgICAgICB8IDcyMyAoODIuNSUpICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgOSAgfCBDTUFRXCAgICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogOC40ICgzKVwgICAgICAgICAgICAgICAgICAgICB8IDYwMSBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEwOS5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMS42IDwgOC42IDwgMjMuMVwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAzLjcgKDAuNCkgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMTAgfCB6Y3RhXCAgICAgICAgICAgICAgICAgICAgICAgIHwgMVwuIDEwMjJcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAhW10odG1wL2RzMDExMC5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbZmFjdG9yXSAgICAgICAgICAgICAgICAgICAgIHwgMlwuIDExMDNcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDIgKCAwLjIlKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgM1wuIDEyMDFcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNFwuIDE2MDhcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDIgKCAwLjIlKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNVwuIDE4MzJcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNlwuIDE4NDBcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgN1wuIDE4NjNcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOFwuIDE5MDRcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOVwuIDIxMTNcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMTBcLiAyMTE5XCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgWyA4MzIgb3RoZXJzIF0gICAgICAgICAgICAgICAgICAgICAgICAgICB8IDg2NCAoOTguNiUpICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMTEgfCB6Y3RhX2FyZWFcICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogMTgzMTczNDgxLjkgKDU0MjU5ODg3OC41KVwgICB8IDg0MiBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDExMS5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMTU0NTkgPCAzNzY1MzU2MC41IDwgODE2NDgyMDYyNVwgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAxNDU4MzY5MDYuNSAoMykgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMTIgfCB6Y3RhX3BvcFwgICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogMjQyMjcuNiAoMTc3NzIuMilcICAgICAgICAgICB8IDgzNyBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDExMi5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDIyMDE0IDwgOTUzOTdcICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAyNTIwNy44ICgwLjcpICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMTMgfCBpbXBfYTUwMFwgICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogMjQuNyAoMTkuMylcICAgICAgICAgICAgICAgICB8IDgxNiBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDExMy5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDI1LjEgPCA2OS42XCAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAzNi41ICgwLjgpICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMTQgfCBpbXBfYTEwMDBcICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogMjQuMyAoMTgpXCAgICAgICAgICAgICAgICAgICB8IDg2MCBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDExNC5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDI0LjUgPCA2Ny41XCAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAzMy4zICgwLjcpICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMTUgfCBpbXBfYTUwMDBcICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogMTkuOSAoMTQuNylcICAgICAgICAgICAgICAgICB8IDg3MCBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDExNS5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMC4xIDwgMTkuMSA8IDc0LjZcICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAyMy4zICgwLjcpICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMTYgfCBpbXBfYTEwMDAwXCAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogMTUuOCAoMTMuOClcICAgICAgICAgICAgICAgICB8IDg3MCBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDExNi5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMC4xIDwgMTIuNCA8IDcyLjFcICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAxOS42ICgwLjkpICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMTcgfCBpbXBfYTE1MDAwXCAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogMTMuNCAoMTMuMSlcICAgICAgICAgICAgICAgICB8IDg3MCBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDExNy5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMC4xIDwgOS43IDwgNzEuMVwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAxNy4zICgxKSAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMTggfCBjb3VudHlfYXJlYVwgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogMzc2ODcwMTk5Mi4xICg2MjEyODI5NTUzLjYpXCB8IDU2NCBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDExOC5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMzM3MDM1MTIgPCAxNjkwODI2NTY2LjUgPCA1MTk0NzIyOTUwOVwgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAxNzYxNjU1OTExLjUgKDEuNikgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMTkgfCBjb3VudHlfcG9wXCAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogNjg3Mjk4LjQgKDEyOTM0ODguNylcICAgICAgICB8IDU2NCBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDExOS5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNzgzIDwgMjgwNzMwLjUgPCA5ODE4NjA1XCAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiA2NDIyMTEgKDEuOSkgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMjAgfCBsb2dfZGlzdF90b19wcmlzZWNcICAgICAgICAgIHwgTWVhbiAoc2QpIDogNi4yICgxLjQpXCAgICAgICAgICAgICAgICAgICB8IDg3MCBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEyMC5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgLTEuNSA8IDYuNCA8IDEwLjVcICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAxLjcgKDAuMikgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMjEgfCBsb2dfcHJpX2xlbmd0aF81MDAwXCAgICAgICAgIHwgTWVhbiAoc2QpIDogOS44ICgxLjEpXCAgICAgICAgICAgICAgICAgICB8IDU4NiBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEyMS5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOC41IDwgMTAuMSA8IDEyXCAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAyLjIgKDAuMSkgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMjIgfCBsb2dfcHJpX2xlbmd0aF8xMDAwMFwgICAgICAgIHwgTWVhbiAoc2QpIDogMTAuOSAoMS4xKVwgICAgICAgICAgICAgICAgICB8IDY4NyBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEyMi5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOS4yIDwgMTEuMiA8IDEzXCAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAyICgwLjEpICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMjMgfCBsb2dfcHJpX2xlbmd0aF8xNTAwMFwgICAgICAgIHwgTWVhbiAoc2QpIDogMTEuNSAoMS4xKVwgICAgICAgICAgICAgICAgICB8IDcyNiBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEyMy5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOS42IDwgMTEuNyA8IDEzLjZcICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAxLjUgKDAuMSkgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMjQgfCBsb2dfcHJpX2xlbmd0aF8yNTAwMFwgICAgICAgIHwgTWVhbiAoc2QpIDogMTIuMiAoMS4xKVwgICAgICAgICAgICAgICAgICB8IDc4NyBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEyNC5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMTAuMSA8IDEyLjUgPCAxNC40XCAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAxLjQgKDAuMSkgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMjUgfCBsb2dfcHJpc2VjX2xlbmd0aF81MDBcICAgICAgIHwgTWVhbiAoc2QpIDogNyAoMSlcICAgICAgICAgICAgICAgICAgICAgICB8IDM4MiBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEyNS5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNi4yIDwgNi4yIDwgOS40XCAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAxLjYgKDAuMSkgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMjYgfCBsb2dfcHJpc2VjX2xlbmd0aF8xMDAwXCAgICAgIHwgTWVhbiAoc2QpIDogOC42ICgwLjgpXCAgICAgICAgICAgICAgICAgICB8IDU5MSBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEyNi5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNy42IDwgOC43IDwgMTAuNVwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAxLjYgKDAuMSkgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMjcgfCBsb2dfcHJpc2VjX2xlbmd0aF81MDAwXCAgICAgIHwgTWVhbiAoc2QpIDogMTEuMyAoMC44KVwgICAgICAgICAgICAgICAgICB8IDg1MiBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEyNy5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOC41IDwgMTEuNCA8IDEyLjhcICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAwLjkgKDAuMSkgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMjggfCBsb2dfcHJpc2VjX2xlbmd0aF8xMDAwMFwgICAgIHwgTWVhbiAoc2QpIDogMTIuNCAoMC43KVwgICAgICAgICAgICAgICAgICB8IDg2NyBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEyOC5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOS4yIDwgMTIuNSA8IDEzLjhcICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAxICgwLjEpICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMjkgfCBsb2dfcHJpc2VjX2xlbmd0aF8xNTAwMFwgICAgIHwgTWVhbiAoc2QpIDogMTMgKDAuNylcICAgICAgICAgICAgICAgICAgICB8IDg2OSBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEyOS5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOS42IDwgMTMuMSA8IDE0LjRcICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAxICgwLjEpICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMzAgfCBsb2dfcHJpc2VjX2xlbmd0aF8yNTAwMFwgICAgIHwgTWVhbiAoc2QpIDogMTMuOCAoMC43KVwgICAgICAgICAgICAgICAgICB8IDg3MCBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEzMC5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMTAuMSA8IDEzLjkgPCAxNS4yXCAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAxICgwLjEpICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMzEgfCBsb2dfbmVpXzIwMDhfcG0yNV9zdW1fMTAwMDBcIHwgTWVhbiAoc2QpIDogNCAoMi40KVwgICAgICAgICAgICAgICAgICAgICB8IDgyOCBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEzMS5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDQuMyA8IDkuMVwgICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAzLjUgKDAuNikgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMzIgfCBsb2dfbmVpXzIwMDhfcG0yNV9zdW1fMTUwMDBcIHwgTWVhbiAoc2QpIDogNC43ICgyLjIpXCAgICAgICAgICAgICAgICAgICB8IDg1NSBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEzMi5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDUgPCA5LjRcICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAyLjkgKDAuNSkgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMzMgfCBsb2dfbmVpXzIwMDhfcG0yNV9zdW1fMjUwMDBcIHwgTWVhbiAoc2QpIDogNS43ICgyLjEpXCAgICAgICAgICAgICAgICAgICB8IDg2MCBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEzMy5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDUuOSA8IDkuN1wgICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAyLjYgKDAuNCkgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMzQgfCBsb2dfbmVpXzIwMDhfcG0xMF9zdW1fMTAwMDBcIHwgTWVhbiAoc2QpIDogNC4zICgyLjMpXCAgICAgICAgICAgICAgICAgICB8IDgyOSBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEzNC5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDQuNiA8IDkuM1wgICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAzLjQgKDAuNSkgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMzUgfCBsb2dfbmVpXzIwMDhfcG0xMF9zdW1fMTUwMDBcIHwgTWVhbiAoc2QpIDogNS4xICgyLjIpXCAgICAgICAgICAgICAgICAgICB8IDg1NSBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEzNS5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDUuNCA8IDkuN1wgICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAyLjggKDAuNCkgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMzYgfCBsb2dfbmVpXzIwMDhfcG0xMF9zdW1fMjUwMDBcIHwgTWVhbiAoc2QpIDogNi4xICgyKVwgICAgICAgICAgICAgICAgICAgICB8IDg2MCBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEzNi5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDYuNCA8IDkuOVwgICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAyLjQgKDAuMykgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMzcgfCBwb3BkZW5zX2NvdW50eVwgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogNTUxLjggKDE3MTEuNSlcICAgICAgICAgICAgICB8IDU2NCBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEzNy5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMC4zIDwgMTU2LjcgPCAyNjgyMS45XCAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiA0NzAgKDMuMSkgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMzggfCBwb3BkZW5zX3pjdGFcICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogMTI3OS43ICgyNzU3LjUpXCAgICAgICAgICAgICB8IDg0MCBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEzOC5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDYxMC4zIDwgMzA0MTguOFwgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAxMjgxLjQgKDIuMikgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMzkgfCBub2hzXCAgICAgICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogNyAoNy4yKVwgICAgICAgICAgICAgICAgICAgICB8IDIxNSBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEzOS5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDUuMSA8IDEwMFwgICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiA2LjEgKDEpICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgNDAgfCBzb21laHNcICAgICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogMTAuMiAoNi4yKVwgICAgICAgICAgICAgICAgICB8IDIzMCBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDE0MC5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDkuNCA8IDcyLjJcICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiA4ICgwLjYpICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgNDEgfCBoc1wgICAgICAgICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogMzAuMyAoMTEuNClcICAgICAgICAgICAgICAgICB8IDM0NyBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDE0MS5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDMwLjggPCAxMDBcICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAxMi4zICgwLjQpICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgNDIgfCBzb21lY29sbGVnZVwgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogMjEuNiAoOC42KVwgICAgICAgICAgICAgICAgICB8IDI0MCBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDE0Mi5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDIxLjMgPCAxMDBcICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiA3LjIgKDAuNCkgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgNDMgfCBhc3NvY2lhdGVcICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogNy4xICg0KVwgICAgICAgICAgICAgICAgICAgICB8IDE1NyBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDE0My5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDcuMSA8IDcxLjRcICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAzLjkgKDAuNikgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgNDQgfCBiYWNoZWxvclwgICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogMTQuOSAoOS43KVwgICAgICAgICAgICAgICAgICB8IDMwMSBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDE0NC5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDEyLjkgPCAxMDBcICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAxMC40ICgwLjcpICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgNDUgfCBncmFkXCAgICAgICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogOC45ICg4LjYpXCAgICAgICAgICAgICAgICAgICB8IDI0NSBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDE0NS5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDYuNyA8IDEwMFwgICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiA3LjEgKDEpICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgNDYgfCBwb3ZcICAgICAgICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogMTUgKDExLjMpXCAgICAgICAgICAgICAgICAgICB8IDM0NSBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDE0Ni5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDEyLjEgPCA2NS45XCAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAxNC43ICgwLjgpICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgNDcgfCBoc19vcmxlc3NcICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogNDcuNSAoMTYuOClcICAgICAgICAgICAgICAgICB8IDQ2NCBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDE0Ny5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDQ4LjcgPCAxMDBcICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAyMS4yICgwLjQpICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgNDggfCB1cmMyMDEzXCAgICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogMi45ICgxLjUpXCAgICAgICAgICAgICAgICAgICB8IDEgOiAyMDMgKDIzLjIlKVwgICAgfCAhW10odG1wL2RzMDE0OC5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8IDIgOiAxNjMgKDE4LjYlKVwgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMSA8IDMgPCA2XCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDMgOiAyMjggKDI2LjAlKVwgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAyICgwLjUpICAgICAgICAgICAgICAgICAgICAgICB8IDQgOiAxMjMgKDE0LjAlKVwgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDUgOiAxMDEgKDExLjUlKVwgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDYgOiAgNTggKCA2LjYlKSAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgNDkgfCB1cmMyMDA2XCAgICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogMyAoMS41KVwgICAgICAgICAgICAgICAgICAgICB8IDEgOiAxOTUgKDIyLjMlKVwgICAgfCAhW10odG1wL2RzMDE0OS5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8IDIgOiAxNjIgKDE4LjUlKVwgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMSA8IDMgPCA2XCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDMgOiAyMjEgKDI1LjIlKVwgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAyICgwLjUpICAgICAgICAgICAgICAgICAgICAgICB8IDQgOiAxMjcgKDE0LjUlKVwgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDUgOiAxMTUgKDEzLjElKVwgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDYgOiAgNTYgKCA2LjQlKSAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgNTAgfCBhb2RcICAgICAgICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogNDMuNyAoMTkuNilcICAgICAgICAgICAgICAgICB8IDU4MSBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDE1MC5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNSA8IDQwLjIgPCAxNDNcICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAxOCAoMC40KSAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCgoKV2UgY2FuIHNlZSB0aGF0IGZvciBtYW55IHZhcmlhYmxlcyB0aGVyZSBhcmUgbWFueSBsb3cgdmFsdWVzIGFzIHRoZSBkaXN0cmlidXRpb24gc2hvd3MgdHdvIHBlYWtzLCBvbmUgbmVhciB6ZXJvIGFuZCBhbm90aGVyIHdpdGggYSBoaWdoZXIgdmFsdWUuIFRoaXMgaXMgdHJ1ZSBmb3IgdGhlIGltcCB2YXJpYWJsZXMgKG1lYXN1cmVzIG9mIGRldmVsb3BtZW50KSwgdGhlIG5laSB2YXJpYWJsZXMgKG1lYXN1cmVzIG9mIGVtaXNzaW9uIHNvdXJjZXMpIGFuZCB0aGUgcm9hZCBkZW5zaXR5IHZhcmlhYmxlcy4gV2UgY2FuIGFsc28gc2VlIHRoYXQgdGhlIHJhbmdlIG9mIHNvbWUgb2YgdGhlIHZhcmlhYmxlcyBpcyB2ZXJ5IGxhcmdlLCBpbiBwYXJ0aWN1bGFyIHRoZSBhcmVhIGFuZCBwb3B1bGF0aW9uIHJlbGF0ZWQgdmFyaWFibGVzLgoKIyMjIEV2YWx1YXRlIGNvcnJlbGF0aW9uIGFtb25nIHBvc3NpYmxlIHByZWRpY3RvcnMKSW4gcHJlZGljdGlvbiBhbmFseXNlcywgaXQgaXMgYWxzbyB1c2VmdWwgdG8gZXZhbHVhdGUgaWYgYW55IG9mIHRoZSB2YXJpYWJsZXMgYXJlIGNvcnJlbGF0ZWQuCgpJbnR1aXRpdmVseSB3ZSBjYW4gZXhwZWN0IHNvbWUgb2Ygb3VyIHZhcmlhYmxlcyB0byBiZSBjb3JyZWxhdGVkLgoKTGV0J3MgZmlyc3QgdGFrZSBhIGxvb2sgYXQgYWxsIG9mIG91ciBudW1lcmljIHZhcmlhYmVscyB3aXRoIHRoZWBjb3JycGxvdGAgcGFja2FnZToKVGhlIGBjb3JycGxvdGAgcGFja2FnZSBpcyBhbm90aGVyIG9wdGlvbiB0byBsb29rIGF0IGNvcnJlbGF0aW9uIGFtb25nIHBvc3NpYmxlIHByZWRpY3RvcnMuIFRoaXMgaXMgYSBncmVhdCBvcHRpb24gaWYgd2UgaGF2ZSBtYW55IHByZWRpY3RvcnMuIApGaXJzdCB3ZSBuZWVkIHRvIGNyZWF0ZSBhIGNvcnJlbGF0aW9uIG1hdHJpeCB1c2luZyB0aGUgYGNvcigpYCBmdW5jdGlvbiBvZiB0aGUgYHN0YXRzYCBwYWNrYWdlICh3aGljaCBpcyBsb2FkZWQgYXV0b21hdGljYWxseSkuCgpgYGB7cn0KbGlicmFyeShSQ29sb3JCcmV3ZXIpClBNX2NvciA8LSBjb3IocG0gJT4lIGRwbHlyOjpzZWxlY3RfaWYoaXMubnVtZXJpYykpCmNvcnJwbG90Ojpjb3JycGxvdChQTV9jb3IsIHRsLmNleCA9IDAuNSkKCmNvcnJwbG90KGFicyhQTV9jb3IpLCBvcmRlciA9ICJBT0UiLCB0bC5jZXggPSAwLjUsICBjbC5saW0gPSBjKDAsIDEpKQoKCmNvcnJwbG90KFBNX2NvciwgZGlhZyA9IEZBTFNFLCBvcmRlciA9ICJGUEMiLAogICAgICAgICB0bC5wb3MgPSAidGQiLCB0bC5jZXggPSAwLjUsIG1ldGhvZCA9ICJjb2xvciIsIHR5cGUgPSAidXBwZXIiLCBjb2wgPSBicmV3ZXIucGFsKG4gPSA4LCBuYW1lID0gIlB1T3IiKSkKCmNvcnJwbG90KFBNX2NvciwgZGlhZyA9IEZBTFNFLAogICAgICAgICB0bC5wb3MgPSAidGQiLCB0bC5jZXggPSAwLjUsIG1ldGhvZCA9ICJjb2xvciIsIHR5cGUgPSAidXBwZXIiKQoKYGBgCgogVXNpbmcgYGdnY29ycGxvdGAKYGBge3J9CmxpYnJhcnkoZ2djb3JycGxvdCkKZ2djb3JycGxvdChQTV9jb3IsIGhjLm9yZGVyID0gVFJVRSwgdHlwZSA9ICJsb3dlciIsIHRsLmNleCA9IDUpCgpgYGAKCldlIGNhbiBzZWUgdGhhdCB0aGUgdGhlIGRldmVsb3BtZW50IHZhcmlhYmxlcyAoaW1wKSB2YXJpYWJsZXMgYXJlIGNvcnJlbGF0ZWQgd2l0aCBlYWNoIG90aGVyIGFzIHdlIG1pZ2h0IGV4cGVjdC4gV2UgYWxzbyBzZWUgdGhhdCB0aGUgcm9hZCBkZW5zaXR5IHZhcmlhYmxlcyBzZWVtIHRvIGJlIGNvcnJlbGF0ZWQgd2l0aCBlYWNoIG90aGVyLCBhbmQgdGhlIGVtaXNzaW9uIHZhcmlhYmxlcyBzZWVtIHRvIGJlIGNvcnJlbGF0ZWQgd2l0aCBlYWNoIG90aGVyLiBXZSBjYW4gdGFrZSBhIGNsb3NlciBsb29rICB1c2luZyB0aGUgYGdnY29ycigpYCBmdW5jdGlvbiBhbmQgdGhlIGBnZ3BhaXJzKClgIGZ1bmN0aW9uIG9mIHRoZSBgR0dhbGx5YCBwYWNrYWdlLiBUbyBzZWxlY3Qgb3VyIHZhcmlhYmxlcyBvZiBpbnRlcmVzdCB3ZSBjYW4gdXNlIHRoZSBgc2VsZWN0KClgIGZ1bmN0aW9uIHdpdGggdGhlIGBjb250YWlucygpYCBmdW5jdGlvbiBvZiB0aGUgYHRpZHlyYCBwYWNrYWdlLiAKCkZpcnN0IGxldCdzIGxvb2sgYXQgdGhlIGltcC9kZXZlbG9wbWVudCB2YXJpYWJsZXMuIApgYGB7ciwgb3V0LndpZHRoID0gIjQwMHB4In0Kc2VsZWN0KHBtLCBjb250YWlucygiaW1wIikpICU+JQogIGdnY29ycihwYWxldHRlID0gIlJkQnUiLCBsYWJlbCA9IFRSVUUpCgpzZWxlY3QocG0sIGNvbnRhaW5zKCJpbXAiKSkgJT4lCiAgZ2dwYWlycygpCiAgCmBgYAoKSW5kZWVkLCB3ZSBjYW4gc2VlIHRoYXQgaW1wX2ExMDAwIGFuZCBpbXBfYTUwMCBhcmUgcGVyZmVjdGx5IGNvcnJlbGF0ZWQsIGFzIHdlbGwgYXMgaW1wX2ExMDAwMCwgaW1wX2ExNTAwMC4KCgpOb3cgbGV0J3MgdGFrZSBhIGxvb2sgYXQgdGhlIHJvYWQgZGVuc2l0eSBkYXRhOgoKYGBge3IsIGZpZy53ZWlnaHQ9MTJ9CnNlbGVjdChwbSwgY29udGFpbnMoInByaSIpKSAlPiUKICBnZ2NvcnIocGFsZXR0ZSA9ICJSZEJ1IiwgIGhqdXN0ID0gLjg1LCBzaXplID0gMywKICAgICAgIGxheW91dC5leHA9MiwgbGFiZWwgPSBUUlVFKQoKc2VsZWN0KHBtLCBjb250YWlucygicHJpIikpICU+JQogIGdncGFpcnMoKQpgYGAKCldlIGNhbiBzZWUgdGhhdCB3aGlsZSBzb21lIG9mIHRoZSByb2FkIGRlbnNpdHkgdmFyaWFibGVzIGFyZSBoaWdobHkgY29ycmVsYXRlZCB3aXRoIG9uZSBhbm90aGVyIChvciBhbnRpLWNvcnJlbGF0ZWQpLCB0aGVyZSBhcnIgc29tZSB2YXJpYWJsZXMgdGhhdCBhcmUgbGVzcyBjb3JyZWxhdGVkIHdpdGggb25lIGFub3RoZXIuCgpGaW5hbGx5IGxldCdzIGxvb2sgYXQgdGhlIGVtaXNzaW9uIHZhcmlhYmxlcy4KCmBgYHtyfQpzZWxlY3QocG0sIGNvbnRhaW5zKCJuZWkiKSkgJT4lCiAgZ2djb3JyKHBhbGV0dGUgPSAiUmRCdSIsICBoanVzdCA9IC44NSwgc2l6ZSA9IDMsCiAgICAgICBsYXlvdXQuZXhwPTIsIGxhYmVsID0gVFJVRSkKCnNlbGVjdChwbSwgY29udGFpbnMoIm5laSIpKSAlPiUKICBnZ3BhaXJzKCkKYGBgCgpXZSB3b3VsZCBhbHNvIGV4cGVjdCB0aGUgcG9wdWxhdGlvbiBkZW5zaXR5IGRhdGEgbWlnaHQgY29ycmVsYXRlIHdpdGggc29tZSBvZiB0aGVzZSB2YXJpYWJsZXMuIExldCdzIHRha2UgYSBsb29rLgoKYGBge3J9CnBtICU+JQpzZWxlY3QobG9nX25laV8yMDA4X3BtMjVfc3VtXzEwMDAwLCBwb3BkZW5zX2NvdW50eSwgbG9nX3ByaV9sZW5ndGhfMTAwMDAsIGltcF9hMTAwMDApICU+JQogIGdnY29ycihwYWxldHRlID0gIlJkQnUiLCAgaGp1c3QgPSAuODUsIHNpemUgPSAzLAogICAgICAgbGF5b3V0LmV4cD0yLCBsYWJlbCA9IFRSVUUpCgpwbSAlPiUKc2VsZWN0KGxvZ19uZWlfMjAwOF9wbTI1X3N1bV8xMDAwMCwgcG9wZGVuc19jb3VudHksIGxvZ19wcmlfbGVuZ3RoXzEwMDAwLCBpbXBfYTEwMDAwLCBjb3VudHlfcG9wKSAlPiUKICBnZ3BhaXJzKCkKYGBgCgoKSW50ZXJlc3RpbmcsIHNvIHRoZXNlIHZhcmlhYmxlcyBkb24ndCBhcHBlYXIgdG8gYmUgaGlnaGx5IGNvcnJlbGF0ZWQsIHRoZXJlZm9yZSB3ZSBtaWdodCBuZWVkIHZhcmlhYmxlcyBmcm9tIGVhY2ggb2YgdGhlIGNhdGVnb3JpZXMgdG8gcHJlZGljdCBvdXIgbW9uaXRvciBQTX4yLjV+IHBvbGx1dGlvbiB2YWx1ZXMuCgpXZSBzZWVtIHRvIGhhdmUgc29tZSBwcmV0dHkgZXh0cmVtZSBwb3B1bGF0aW9uIHZhbHVlcyB0aG91Z2gsIHNvIGxldCdzIHNlZSB3aGF0IGhhcHBlbnMgd2hlbiB3ZSB0YWtlIHRoZSBsb2cgdmFsdWUuCgpgYGB7cn0KcG0gJT4lCiAgbXV0YXRlKGxvZ19wb3BkZW5zX2NvdW50eT0gbG9nKHBvcGRlbnNfY291bnR5KSkgJT4lCnNlbGVjdChsb2dfbmVpXzIwMDhfcG0yNV9zdW1fMTAwMDAsIGxvZ19wb3BkZW5zX2NvdW50eSwgbG9nX3ByaV9sZW5ndGhfMTAwMDAsIGltcF9hMTAwMDApICU+JQogIGdnY29ycihwYWxldHRlID0gIlJkQnUiLCAgaGp1c3QgPSAuODUsIHNpemUgPSAzLAogICAgICAgbGF5b3V0LmV4cD0yLCBsYWJlbCA9IFRSVUUpCgpwbSAlPiUKICBtdXRhdGUobG9nX3BvcGRlbnNfY291bnR5PSBsb2cocG9wZGVuc19jb3VudHkpKSAlPiUKICBtdXRhdGUobG9nX3BvcF9jb3VudHkgPSBsb2coY291bnR5X3BvcCkpICU+JQpzZWxlY3QobG9nX25laV8yMDA4X3BtMjVfc3VtXzEwMDAwLCBsb2dfcG9wZGVuc19jb3VudHksIGxvZ19wcmlfbGVuZ3RoXzEwMDAwLCBpbXBfYTEwMDAwLCBsb2dfcG9wX2NvdW50eSkgJT4lCiAgZ2dwYWlycygpCmBgYAoKSW5kZWVkIHRoaXMgaW5jcmVhc2VkIHRoZSBjb3JyZWxhdGlvbiwgYnV0IHZhcmlhYmxlcyBmcm9tIGVhY2ggb2YgdGhlc2UgY2F0ZWdvcmllcyBtYXkgc3RpbGwgcHJvdmUgdG8gYmUgdXNlZnVsIGZvciBwcmVkaWN0aW9uLgoKCgoKIyMgRGF0YSBBbmFseXNpcwoKTm93IHRoYXQgd2UgaGF2ZSBhIHNlbnNlIG9mIHdoYXQgb3VyIGRhdGEgaXMgbGlrZSB3ZSBjYW4gZ2V0IHN0YXJ0ZWQgd2l0aCBkYXRhIGFuYWx5c2lzLgoKCiMjIyBUaGUgdGlkeW1vZGVscyBlY29zeXN0ZW0KClRvIHBlcmZvcm0gb3VyIGFuYWx5c2lzIHdlIHdpbGwgYmUgdXNpbmcgdGhlIGB0aWR5bW9kZWxzYCBzdWl0ZSBvZiBwYWNrYWdlcy4gWW91IG1heSBiZSBmYW1pbGlhciB3aXRoIHRoZSBvbGRlciBwYWNrYWdlcyBgY2FyZXRgIG9yIGBtbHJgIHdoaWNoIGFyZSBhbHNvIGZvciBtYWNoaW5lIGxlYXJuaW5nIGFuZCBtb2RlbGluZyBidXQgYXJlIG5vdCBhIHBhcnQgb2YgdGhlIGB0aWR5dmVyc2VgLiBbTWF4IEt1aG5dKGh0dHBzOi8vcmVzb3VyY2VzLnJzdHVkaW8uY29tL2F1dGhvcnMvbWF4LWt1aG4pe3RhcmdldD0iX2JsYW5rIn0gZGVzY3JpYmVzIGB0aWR5bW9kZWxzYCBsaWtlIHRoaXM6Cgo+ICJPdGhlciBwYWNrYWdlcywgc3VjaCBhcyBjYXJldCBhbmQgbWxyLCBoZWxwIHRvIHNvbHZlIHRoZSBSIG1vZGVsIEFQSSBpc3N1ZS4gVGhlc2UgcGFja2FnZXMgZG8gYSBsb3Qgb2Ygb3RoZXIgdGhpbmdzIHRvbzogcHJlcHJvY2Vzc2luZywgbW9kZWwgdHVuaW5nLCByZXNhbXBsaW5nLCBmZWF0dXJlIHNlbGVjdGlvbiwgZW5zZW1ibGluZywgYW5kIHNvIG9uLiBJbiB0aGUgdGlkeXZlcnNlLCB3ZSBzdHJpdmUgdG8gbWFrZSBvdXIgcGFja2FnZXMgbW9kdWxhciBhbmQgcGFyc25pcCBpcyBkZXNpZ25lZCBvbmx5IHRvIHNvbHZlIHRoZSBpbnRlcmZhY2UgaXNzdWUuIEl0IGlzIG5vdCBkZXNpZ25lZCB0byBiZSBhIGRyb3AtaW4gcmVwbGFjZW1lbnQgZm9yIGNhcmV0LgpUaGUgdGlkeW1vZGVscyBwYWNrYWdlIGNvbGxlY3Rpb24sIHdoaWNoIGluY2x1ZGVzIHBhcnNuaXAsIGhhcyBvdGhlciBwYWNrYWdlcyBmb3IgbWFueSBvZiB0aGVzZSB0YXNrcywgYW5kIHRoZXkgYXJlIGRlc2lnbmVkIHRvIHdvcmsgdG9nZXRoZXIuIFdlIGFyZSB3b3JraW5nIHRvd2FyZHMgaGlnaGVyLWxldmVsIEFQSXMgdGhhdCBjYW4gcmVwbGljYXRlIGFuZCBleHRlbmQgd2hhdCB0aGUgY3VycmVudCBtb2RlbCBwYWNrYWdlcyBjYW4gZG8uIgoKCiMjIyBUaGUgbWFqb3IgYmVuZWZpdHMgb2YgdGlkeW1vZGVscwoxKSBzdGFuZGFyZGl6ZWQgd29ya2Zsb3cvZm9ybWF0L25vdGF0aW9uIGFjcm9zcyBkaWZmZXJlbnQgdHlwZXMgb2YgYWxnb3JpdGhtcwoyKSBjYW4gZWFzaWx5IG1vZGlmeSBwcmVwcm9jZXNzaW5nLCBhbGdvcml0aG0gY2hvaWNlLCBhbmQgaHlwZXItcGFyYW1ldGVyIHR1bmluZyBtYWtpbmcgb3B0aW1pemF0aW9uIGVhc3kKCgojIyMgVGhlIG1hY2hpbmUgbGVhcm5pbmcgcHJvY2VzcwoKCiMjIyBUaGUgdGlkeW1vZGVscyBlY29zeXN0ZW0gLSBhbiBvdmVydmlldwoKVGhlcmUgYXJlIG1hbnkgcGFja2FnZXMgaW4gdGhlIHRpZHltb2RlbHMgZWNvc3lzdGVtIHdoaWNoIGFzc2lzdCB3aXRoIHRoZSB2YXJpb3VzIHN0ZXBzIG9mIHRoZSBtYWNoaW5lIGxlYXJuaW5nIHByb2Nlc3M6CgpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI4MDBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsInNpbXBsZXRpZHltb2RlbHMucG5nIikpCmBgYAoKClRoaXMgaXMgdGhlIG92ZXJhbGwgcHJvY2VzczoKCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjgwMHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwiTWFjaGluZUxlYXJuaW5nLnBuZyIpKQpgYGAKClRoZXJlIGFyZSB0d28gZGlzdGluY3QgZ29hbHMgb2Ygc3VwZXJ2aXNlZCBtYWNoaW5lIGxlYXJuaW5nOiAgCgoxKSBQcmVkaWN0aW9uICAKMikgQ2xhc3NpZmljYXRpb24gIAoKV2Ugd2lsbCBiZSBwZXJmb3JtaW5nIGEgcHJlZGljdGlvbiBhbmFseXNpcyAod2hpY2ggaXMgYWxzbyByZWZlcmVkIHRvIGFzIHJlZ3Jlc3Npb24pLCB3aGljaCBhaW1zIHRvIHByZWRpY3QgKipjb250aW51b3VzIG91dGNvbWUqKiB2YXJpYWJsZXMgZ2l2ZW4gYSBudW1iZXIgb2YgcHJlZGljdG9ycy9leHBsYW5hdG9yeSB2YXJpYWJsZXMvZmVhdHVyZXMvcGFyYW1ldGVycywgYXMgd2UgaGF2ZSBhbHJlYWR5IGRlc2NyaWJlZC4KCkNsYXNzaWZpY2F0aW9uIG9uIHRoZSBvdGhlciBoYW5kIGFpbXMgdG8gZGlzY2VybiBvciBwcmVkaWN0IGdyb3VwIGlkZW50aXR5IGZvciBhICoqY2F0ZWdvcmljYWwgb3V0Y29tZSoqIGJhc2VkIG9uIGEgbnVtYmVyIG9mIHByZWRpY3RvcnMvZXhwbGFuYXRvcnkgdmFyaWFibGVzL2ZlYXR1cmVzL3BhcmFtZXRlcnMuCgpUaGUgb3ZlcmFsbCBwcm9jZXNzIGlzIHRoZSBzYW1lIGluIGVpdGhlciBjYXNlLiAKCiMjIyBTcGxpdHRpbmcgdGhlIERhdGEKClRoZSBmaXJzdCBzdGVwIGFmdGVyIGRhdGEgZXhwbG9yYXRpb24gaW4gbWFjaGluZSBsZWFybmluZyBhbmFseXNpcyBpcyB0byBbc3BsaXQgdGhlIGRhdGFdKGh0dHBzOi8vdG93YXJkc2RhdGFzY2llbmNlLmNvbS90cmFpbi12YWxpZGF0aW9uLWFuZC10ZXN0LXNldHMtNzJjYjQwY2JhOWU3KXt0YXJnZXQ9Il9ibGFuayJ9IGludG8gKip0cmFpbmluZyoqIGFuZCAqKnRlc3RpbmcqKiBkYXRhc2V0cy4gCgpUaGUgdHJhaW5pbmcgZGF0YXNldCB3aWxsIGJlIHVzZWQgdG8gYnVpbGQgYW5kIHR1bmUgb3VyIG1vZGVsLiBUaGlzIGlzIHRoZSBkYXRhIHRoYXQgdGhlIG1vZGVsICJsZWFybnMiIG9uLgoKVGhlIHRlc3Rpbmcgc2V0IHdpbGwgYmUgdXNlZCB0byBldmFsdWF0ZSB0aGUgcGVyZm9ybWFuY2Ugb2Ygb3VyIG1vZGVsIGluIGEgbW9yZSBnZW5lcmFsaXphYmxlIHdheS4gV2hhdCBkbyB3ZSBtZWFuIGJ5ICJnZW5lcmFsaXphYmxlIj8KClJlbWVtYmVyIHRoYXQgb3VyIG1haW4gZ29hbCBpcyB0byB1c2Ugb3VyIG1vZGVsIHRvIGJlIGFibGUgdG8gcHJlZGljdCBhaXIgcG9sbHV0aW9uIGxldmVscyBpbiBhcmVhcyB3aGVyZSB0aGVyZSBhcmUgbm8gZ3JhdmltZXRyaWMgbW9uaXRvcnMuIFRoZXJlZm9yZSwgaWYgb3VyIG1vZGVsIGlzIHN1cGVyIGdvb2QgYXQgcHJlZGljdGluZyBhaXIgcG9sbHV0aW9uIHdpdGggdGhlIGRhdGEgdGhhdCB3ZSB1c2UgdG8gYnVpbGQgaXQsIGl0IG1pZ2h0IG5vdCBkbyB0aGUgYmVzdCBqb2IgZm9yIHRoZSBhcmVhcyB3aGVyZSB0aGVyZSBhcmUgZmV3IHRvIG5vIG1vbml0b3JzLiBUaGlzIHdvdWxkIGNhdXNlIHVzIHRvIGhhdmUgcmVhbGx5IGdvb2QgcHJlZGljdGlvbiBhY2N1cmFjeSBhbmQgd2UgbWlnaHQgYXNzdW1lIHRoYXQgd2Ugd2VyZSBnb2luZyB0byBkbyBhIGdvb2Qgam9iIGVzdGltYXRpbmcgYWlyIHBvbGx1dGlvbiBhbnkgdGltZSB3ZSB1c2Ugb3VyIG1vZGVsLCBidXQgaW4gZmFjdCB0aGlzIHdvdWxkIGxpa2VseSBub3QgYmUgdGhlIGNhc2UuIFRoaXMgc2l0dWF0aW9uIGlzIHdoYXQgd2UgY2FsbCAqKltvdmVyZml0dGluZ10oaHR0cHM6Ly90b3dhcmRzZGF0YXNjaWVuY2UuY29tL3RyYWluLXRlc3Qtc3BsaXQtYW5kLWNyb3NzLXZhbGlkYXRpb24taW4tcHl0aG9uLTgwYjYxYmVjYTRiNil7dGFyZ2V0PSJfYmxhbmsifSAqKi4KCk92ZXJmaXR0aW5nIGhhcHBlbnMgd2hlbiB3ZSBlbmQgdXAgbW9kZWxpbmcgbm90IG9ubHkgdGhlIG1ham9yIHJlbGF0aW9uc2hpcHMgaW4gb3VyIGRhdGEgYnV0IGFsc28gdGhlIG5vaXNlIHdpdGhpbiBvdXIgZGF0YS4gCgoKYGBge3J9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJodHRwczovL21pcm8ubWVkaXVtLmNvbS9tYXgvMTExMC8xKnRCRXJYWVZ2VHcyalNVWUs3dGhVMkEucG5nIikKYGBgCgojIyMjIyBbW3NvdXJjZV0oaHR0cHM6Ly9taXJvLm1lZGl1bS5jb20vbWF4LzExMTAvMSp0QkVyWFlWdlR3MmpTVVlLN3RoVTJBLnBuZyldCgpJZiB3ZSBnZXQgZmFpcmx5IGdvb2QgcHJlZGljdGlvbiB3aXRoIG91ciB0ZXN0aW5nIHNldCB0aGVuIHdlIHdpbGwga25vdyB0aGF0IG91ciBtb2RlbCBjYW4gYmUgYXBwbGllZCB0byBvdGhlciBkYXRhIGFuZCB3aWxsIHBlcmZvcm0gZmFpcmx5IHdlbGwuIFdlIHdpbGwgZGlzY3VzcyB0aGlzIG1vcmUgbGF0ZXIuCgpXZSB3aWxsIG5vdCB0b3VjaCB0aGUgdGVzdGluZyBzZXQgdW50aWwgd2UgaGF2ZSBjb21wbGV0ZWQgb3B0aW1pemluZyBvdXIgbW9kZWwgd2l0aCB0aGUgdHJhaW5pbmcgc2V0LiBUaGlzIHdpbGwgYWxsb3cgdXMgdG8gaGF2ZSBhIGxlc3MgYmlhc2VkIGV2YWx1YXRpb24gb2YgaG93IHdlbGwgb3VyIG1vZGVsIGNhbiBkbyB3aXRoIG90aGVyIGRhdGEgYmVzaWRlcyB0aGUgZGF0YSB1c2VkIGluIHRoZSB0cmFpbmluZyBzZXQgdG8gYnVpbGQgdGhlIG1vZGVsLiBJZGVhbGx5IHlvdSB3b3VsZCBhbHNvIHdhbnQgYSBjb21wbGV0ZWx5IGluZGVwZW5kZW50IGRhdGFzZXQgdG8gZnVydGhlciB0ZXN0IHRoZSBwZXJmb3JtYW5jZSBvZiB5b3VyIG1vZGVsLgoKW0hlcmVdKGh0dHBzOi8vbWFjaGluZWxlYXJuaW5nbWFzdGVyeS5jb20vZGlmZmVyZW5jZS10ZXN0LXZhbGlkYXRpb24tZGF0YXNldHMvKXt0YXJnZXQ9Il9ibGFuayJ9IGlzIGEgZ3JlYXQgZGVzY3JpcHRpb24gb2YgdGhlIGRpZmZlcmVuY2VzIGJldHdlZW4gdGVzdGluZyBhbmQgdHJhaW5pbmcgZGF0YXNldHMuCgpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI0MDBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsInNwbGl0LnBuZyIpKQpgYGAKV2Ugd2lsbCB1c2UgdGhlIGByc2FtcGxlYCBwYWNrYWdlIHRvIHBlcmZvcm0gdGhpcyBzdGVwLgoKVGhlYGluaXRpYWxfc3BsaXQoKWAgZnVuY3Rpb24gYWxsb3dzIHVzIHRvIHNwZWNpZnkgaG93IHdlIHdhbnQgdG8gc3BsaXQgb3VyIGRhdGEuIFR5cGljYWxseSBkYXRhIGlzIHNwbGl0IGludG8gMy80IGZvciB0cmFpbmluZyBhbmQgMS80IGZvciB0ZXN0aW5nLlRoaXMgaXMgdGhlIGRlZmF1bHQgcHJvcG9ydGlvbiBhbmQgZG9lcyBub3QgbmVlZCB0byBiZSBzcGVjaWZpZWQuIEhvd2V2ZXIgeW91IGNhbiBjaGFuZ2UgdGhlIHByb3BvcnRpb24gdXNpbmcgdGhlIGBwcm9wYCBhcmd1bWVudCwgd2hpY2ggd2Ugd2lsbCBkbyB0aGF0IGhlcmUgZm9yIGlsbHVzdHJhdGl2ZSBwdXJwb3Nlcy4gWW91IGNhbiBhbHNvIHNwZWNpZnkgYSB2YXJpYWJsZSB0byBzdHJhdGlmeSBieSB3aXRoIHRoZSBgc3RyYXRhYCBhcmd1bWVudC4gVGhpcyBpcyB1c2VmdWwgaWYgeW91IGhhdmUgaW1iYWxhbmNlZCBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgYW5kIHlvdSB3b3VsZCBsaWtlIHRvIGludGVudGlvbmFsbHkgbWFrZSBzdXJlIHRoYXQgdGhlcmUgYXJlIHNpbWlsYXIgbnVtYmVyIG9mIHNhbXBsZXMgb2YgdGhlIHJhcmVyIGNhdGVnb3JpZXMgaW4gYm90aCB0aGUgdGVzdGluZyBhbmQgdHJhaW5pbmcgc2V0cy4gT3RoZXJ3aXNlIHRoZSBzcGxpdCBpcyBwZXJmb3JtZWQgcmFuZG9tbHkuIAoKPiBUaGUgc3RyYXRhIGFyZ3VtZW50IGNhdXNlcyB0aGUgcmFuZG9tIHNhbXBsaW5nIHRvIGJlIGNvbmR1Y3RlZCB3aXRoaW4gdGhlIHN0cmF0aWZpY2F0aW9uIHZhcmlhYmxlLiBUaGUgY2FuIGhlbHAgZW5zdXJlIHRoYXQgdGhlIG51bWJlciBvZiBkYXRhIHBvaW50cyBpbiB0aGUgdHJhaW5pbmcgZGF0YSBpcyBlcXVpdmFsZW50IHRvIHRoZSBwcm9wb3J0aW9ucyBpbiB0aGUgb3JpZ2luYWwgZGF0YSBzZXQuCgpJbiB0aGUgY2FzZSB3aXRoIG91ciBkYXRhc2V0LCBwZXJoYXBzIHdlIHdvdWxkIGxpa2Ugb3VyIHRyYWluaW5nIHNldCB0byBoYXZlIHNpbWlsYXIgcHJvcG9ydGlvbnMgb2YgbW9uaXRvcnMgZnJvbSBlYWNoIG9mIHRoZSBzdGF0ZXMgYXMgaW4gdGhlIGluaXRpYWwgZGF0YS4gVGhpcyBtaWdodCBiZSB1c2VmdWwgaWYgd2Ugd2FudCBvdXIgbW9kZWwgdG8gYmUgZ2VuZXJhbGl6YWJsZSBhY3Jvc3MgYWxsIG9mIHRoZSBzdGF0ZXMuCgpXZSBjYW4gc2VlIHRoYXQgaW5kZWVkIHRoZXJlIGFyZSBkaWZmZXJlbnQgcHJvcG9ydGlvbnMgb2YgbW9uaXRvcnMgaW4gZWFjaCBzdGF0ZSBieSB1c2luZyB0aGUgYGNvdW50KClgIGZ1bmN0aW9uIG9mIHRoZSBgZHB5cmAgcGFja2FnZS4gCgojIyMjIHsuc2Nyb2xsYWJsZSB9CmBgYHtyfQojIFNjcm9sbCB0aHJvdWdoIHRoZSBvdXRwdXQhCmNvdW50KHBtLCBzdGF0ZSkgJT4lCiAgcHJpbnQobiA9IDFlMykKYGBgCiMjIyMKCklmIG91ciBkYXRhc2V0IHdlcmUgbGFyZ2UgZW5vdWdoIGl0IG1pZ2h0IGJlIG5pY2UgdGhlbiB0byBzdHJhdGlmeSBieSBzdGF0ZSwgYnV0IG91ciBkYXRhIGlzIHVuZm9ydHVuYXRlbHkgbm90IGxhcmdlIGVub3VnaC4gV2Ugd2lsbCBzaG93IGhvdyBvbmUgd291bGQgZG8gdGhpcyB0aG91Z2ggZm9yIGlsbHVzdHJhdGl2ZSBwdXJwb3Nlcy4gVGhpcyBvcHRpb24gaXMgb2Z0ZW4gbW9yZSBpbXBvcnRhbnQgZm9yIGNsYXNzaWZpY2F0aW9uIGFwcGxpY2F0aW9ucyBvZiBtYWNoaW5lIGxlYXJuaW5nIHRoYW4gaXQgaXMgZm9yIHByZWRpY3Rpb24uCgpTaW5jZSB0aGUgc3BsaXQgaXMgcGVyZm9ybWVkIHJhbmRvbWx5LCBpdCBpcyBhIGdvb2QgaWRlYSB0byB1c2UgdGhlIGBzZXQuc2VlZCgpYCBiYXNlIGZ1bmN0aW9uIHRvIGVuc3VyZSB0aGF0IGlmIHlvdXIgcmVydW4geW91ciBjb2RlIHRoYXQgeW91ciBzcGxpdCB3aWxsIGJlIHRoZSBzYW1lIG5leHQgdGltZS4gV2UgY2FuIHNlZSB0aGUgbnVtYmVyIG9mIG1vbml0b3JzIGluIG91ciB0cmFpbmluZywgdGVzdGluZywgYW5kIG9yaWdpbmFsIGRhdGEgYnkgdHlwaW5nIGluIHRoZSBuYW1lIG9mIG91ciBzcGxpdCBvYmplY3QuIFRoZSByZXN1bHQgd2lsbCBsb29rIGxpa2UgdGhpczoKPHRyYWluaW5nIGRhdGEgc2FtcGxlIG51bWJlciwgdGVzdGluZyBkYXRhIHNhbXBsZSBudW1iZXIsIG9yaWdpbmFsIHNhbXBsZSBudW1iZXI+IAoKYGBge3J9CnNldC5zZWVkKDEyMzQpCnBtX3NwbGl0IDwtcnNhbXBsZTo6aW5pdGlhbF9zcGxpdChkYXRhID0gcG0sIHByb3AgPSAyLzMpCnBtX3NwbGl0CgojIElmIHN0cmF0aWZ5aW5nOgojIHBtX3NwbGl0X3N0cmF0YSA8LXJzYW1wbGU6OmluaXRpYWxfc3BsaXQoZGF0YSA9IHBtLCBwcm9wID0gMi8zLCBzdHJhdGEgPSAic3RhdGUiKQoKYGBgCgpJbXBvcnRhbnRseSB0aGUgYGluaXRpYWxfc3BsaXRgIGZ1bmN0aW9uIG9ubHkgZGV0ZXJtaW5lcyB3aGF0IHJvd3Mgb2Ygb3VyIHBtIGRhdGEgZnJhbWUgc2hvdWxkIGJlIGFzc2lnbmVkIGZvciB0cmFpbmluZyBvciB0ZXN0aW5nLCBpdCBkb2VzIG5vdCBhY3R1YWxseSBzcGxpdCB0aGUgZGF0YS4gCgpUbyBleHRyYWN0IHRoZSB0ZXN0aW5nIGFuZCB0cmFpbmluZyBkYXRhIHdlIGNhbiB1c2UgdGhlIGB0cmFpbmluZygpYCBhbmQgYHRlc3RpbmcoKWAgZnVuY3Rpb25zIGFsc28gb2YgdGhlIGByc2FtcGxlYCBwYWNrYWdlLgoKIyMjIyB7LnNjcm9sbGFibGUgfQpgYGB7cn0KIHRyYWluX3BtIDwtcnNhbXBsZTo6dHJhaW5pbmcocG1fc3BsaXQpCiB0ZXN0X3BtIDwtcnNhbXBsZTo6dGVzdGluZyhwbV9zcGxpdCkKIAojIFNjcm9sbCB0aHJvdWdoIHRoZSBvdXRwdXQhCmNvdW50KHRyYWluX3BtLCBzdGF0ZSkKY291bnQodGVzdF9wbSwgc3RhdGUpCmBgYAojIyMjCgoKCiMjIyBWYXJpYWJsZSBSb2xlIEFzc2lnbm1lbnQgYW5kIFByZXByb2Nlc3NpbmcKCkluIHRpZHltb2RlbHMgd2Ugd2lsbCBjcmVhdGUgYSByZWNpcGUsIHdoaWNoIGlzIGEgc3RhbmRhcmRpemVkIGZvcm1hdCBmb3IgYSBzZXF1ZW5jZSBvZiBzdGVwcyBmb3IgcHJvY2Vzc2luZyB0aGUgZGF0YS4KClRoaXMgY2FuIGJlIHZlcnkgdXNlZnVsIGJlY2F1c2UgaXQgbWFrZXMgdGVzdGluZyBvdXQgZGlmZmVyZW50IHByZS1wcm9jZXNzaW5nIHN0ZXBzIG9yIGRpZmZlcmVudCBhbGdvcml0aG1zIHdpdGggdGhlIHNhbWUgcHJlLXByb2Nlc3NpbmcgdmVyeSBlYXN5IGFuZCByZXByb2R1Y2libGUuCgoqKkNyZWF0aW5nIGEgcmVjaXBlIHNwZWNpZmllcyBob3cgYSBkYXRhZnJhbWUgb2YgcHJlZGljdG9ycyBzaG91bGQgYmUgY3JlYXRlZCAgLSBpdCBzcGVjaWZpZXMgd2hhdCAgdmFyaWFibGVzIHRvIGJlIHVzZWQgIGFuZCB0aGUgIHByZXByb2Nlc3Npbmcgc3RlcHMgIGJ1dCBpdCBkb2VzIG5vdCBleGVjdXRlIHRoZXNlIHN0ZXBzIG9yIGNyZWF0ZSB0aGUgZGF0YWZyYW1lIG9mIHByZWRpY3RvcnMuKioKCiMjIyMgTGlzdCB0aGUgaW5ncmVkaWVudHMgLyBzcGVjaWZ5IHRoZSB2YXJpYWJsZXMgd2l0aCB0aGUgYHJlY2lwZSgpYCBmdW5jdGlvbgoKVGhlIGZpcnN0IHRoaW5nIHRvIGRvIHRvIGNyZWF0ZSBhIHJlY2lwZSBpcyB0byBzcGVjaWZ5IHdoaWNoIHZhcmlhYmxlcyB3ZSB3aWxsIGJlIHVzaW5nIGFzIG91ciBvdXRjb21lIGFuZCBwcmVkaWN0b3JzIHVzaW5nIHRoZSBgcmVjaXBlKClgIGZ1bmN0aW9uLiBJbiB0ZXJtcyBvZiB0aGUgbWV0YXBob3Igb2YgYmFraW5nLCB3ZSBjYW4gdGhpbmsgb2YgdGhpcyBhcyBsaXN0aW5nIG91ciBpbmdyZWRpZW50cy4gVGhlIG5hbWluZyBjb252ZW50aW9uIGZvciByZWNpcGUgb2JqZWN0IG5hbWVzIGlzIGAqX3JlY2Agb3IgYHJlY2AuIAoKYGBge3IsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iNDAwcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJTdGFydGluZ19hX3JlY2lwZV9yZWNpcGVzMS5wbmciKSkKYGBgCgoKSW4gb3VyIGNhc2UgcmVjYWxsIHRoYXQgb3VyIGB2YWx1ZWAgdmFyaWFibGUsIHdoaWNoIGlzIHRoZSBhdmVyYWdlIGFubnVhbCBncmF2aW1ldHJpYyBtb25pdG9yIFBNfjIuNX4gY29uY2VudHJhdGlvbiBpbiB1Zy9tXjNeLiBPdXIgcHJlZGljdG9ycyBhcmUgYWxsIHRoZSBvdGhlciB2YXJpYWJsZXMgZXhjZXB0IHRoZSBtb25pdG9yIElELCB3aGljaCBpcyBhbiBgaWRgIHZhcmlhYmxlLgoKVGhlIHJlYXNvbiBub3QgdG8gaW5jbHVkZSB0aGlzIHZhcmlhYmxlIGlzIGJlY2F1c2UgdGhpcyB2YXJpYWJsZSBpbmNsdWRlcyB0aGUgY291bnR5IG51bWJlciBhbmQgYSBudW1iZXIgZGVzaWduYXRpbmcgd2hpY2ggcGFydGljdWxhciBtb25pdG9yIHRoZSB2YWx1ZXMgY2FtZSBmcm9tIG9mIHRoZSBtb25pdG9ycyB0aGVyZSBhcmUgaW4gdGhhdCBjb3VudHkuIFNpbmNlIHRoaXMgbnVtYmVyIGlzIGFyYml0cmFyeSBhbmQgdGhlIGNvdW50eSBpbmZvcm1hdGlvbiBpcyBhbHNvIGdpdmVuIGluIHRoZSBkYXRhLCBhbmQgdGhlIGZhY3QgdGhhdCBlYWNoIG1vbml0b3Igb25seSBoYXMgb25lIHZhbHVlIGluIHRoZSBgdmFsdWVgIHZhcmlhYmxlLCBub3RoaW5nIGlzIGdhaW5lZCBieSBpbmNsdWRpbmcgdGhpcyB2YXJpYWJsZSBhbmQgaXQgbWF5IGluc3RlYWQgaW50cm9kdWNlIG5vaXNlLiBIb3dldmVyLCBpdCBpcyB1c2VmdWwgdG8ga2VlcCB0aGlzIGRhdGEgdG8gdGFrZSBhIGxvb2sgYXQgd2hhdCBpcyBoYXBwZW5pbmcgbGF0ZXIuIFdlIHdpbGwgc2hvdyB5b3Ugd2hhdCB0byBkbyBpbiB0aGlzIGNhc2UgaW4ganVzdCBhIGJpdC4KClRoZSBzaW1wbGVzdCByZWNpcGUgd2l0aCBubyBwcmVwcm9jZXNzaW5nIHN0ZXBzLCB3b3VsZCBiZSB0byBzaW1wbHkgbGlzdCB0aGUgb3V0Y29tZSBhbmQgcHJlZGljdG9yIHZhcmlhYmxlcy4KCldlIGNhbiBkbyBzbyBpbiB0d28gd2F5czogIAoKMSkgVXNpbmcgZm9ybXVsYSBub3RhdGlvbiAgCjIpIEFzc2lnbmluZyByb2xlcyB0byBlYWNoIHZhcmlhYmxlICAKCkxldCdzIGxvb2sgYXQgdGhlIGZpcnN0IHdheSB1c2luZyBmb3JtdWxhIG5vdGF0aW9uLCB3aGljaCBsb29rcyBsaWtlIHRoaXM6ICAKCm91dGNvbWUocykgfiBwcmVkaWN0b3IocykgIAoKSWYgaW4gdGhlIGNhc2Ugb2YgbXVsdGlwbGUgcHJlZGljdG9ycyBvciBhIG11bHRpdmFyaWF0ZSBzaXR1YXRpb24gd2l0aCB0d28gb3V0Y29tZXMsIHVzZSBhIHBsdXMgc2lnbiAgCgpvdXRjb21lMSArIG91dGNvbWUyIH4gcHJlZGljdG9yMSArIHByZWRpY3RvcjIgIAoKSWYgd2Ugd2FudCB0byBpbmNsdWRlIGFsbCBwcmVkaWN0b3JzIHdlIGNhbiB1c2UgYSBwZXJpb2QgbGlrZSBzbzogIAoKb3V0Y29tZV92YXJpYWJsZV9uYW1lIH4gLiAgCgpOb3cgd2l0aCBvdXIgZGF0YSB3ZSB3aWxsIHN0YXJ0IGJ5IG1ha2luZyBhIHJlY2lwZSBmb3Igb3VyIHRyYWluaW5nIGRhdGEuIEluIHRoZSBzaW1wbGVzdCBjYXNlIHdlIG1pZ2h0IHVzZSBhbGwgcHJlZGljdG9ycyBsaWtlIHRoaXM6CgpgYGB7cn0KCnNpbXBsZV9yZWMgPC10cmFpbl9wbSAlPiUKICByZWNpcGVzOjpyZWNpcGUodmFsdWUgfiAuKQoKc2ltcGxlX3JlYwpgYGAKCgpIb3dldmVyLCB0byBkZWFsIHdpdGggdGhlIGlkIHZhcmlhYmxlIHdlIGNvdWxkIHVzZSB0aGUgYHVwZGF0ZV9yb2xlKClgIGZ1bmN0aW9uIG9mIHRoZSBgcmVjaXBlc2AgcGFja2FnZToKCmBgYHtyfQoKc2ltcGxlX3JlYyA8LXRyYWluX3BtICU+JQogIHJlY2lwZXM6OnJlY2lwZSh2YWx1ZSB+IC4pICU+JQogIHJlY2lwZXM6OnVwZGF0ZV9yb2xlKGlkLCBuZXdfcm9sZSA9ICJpZCB2YXJpYWJsZSIpCgpzaW1wbGVfcmVjCmBgYAoKV2UgY291bGQgYWxzbyBzcGVjaWZ5IHRoZSBvdXRjb21lIGFuZCBwcmVkaWN0b3JzIGluIHRoZSBzYW1lIHdheSBhcyB0aGUgaWQgdmFyaWFibGUuIFBsZWFzZSBzZWUgW2hlcmVdKGh0dHBzOi8vdGlkeW1vZGVscy5naXRodWIuaW8vcmVjaXBlcy9yZWZlcmVuY2UvcmVjaXBlLmh0bWwpIGZvciBleGFtcGxlcyBvZiBvdGhlciByb2xlcyBmb3IgdmFyaWFibGVzLiBUaGUgcm9sZSBjYW4gYmUgYWN0dWFsbHkgYmUgYW55IHZhbHVlLiAKClRoZSBvcmRlciBpcyBpbXBvcnRhbnQgaGVyZSwgYXMgd2UgZmlyc3QgbWFrZSBhbGwgdmFyaWFibGVzIHByZWRpY3RvcnMgYW5kIHRoZW4gb3ZlcnJpZGUgdGhpcyByb2xlIGZvciB0aGUgb3V0Y29tZSBhbmQgaWQgdmFyaWFibGUuIFdlIHdpbGwgdXNlIHRoZSBgZXZlcnl0aGluZygpYCBmdW5jdGlvbiBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlIHRvIHN0YXJ0IHdpdGggYWxsIG9mIHRoZSB2YXJpYWJsZXMgaW4gYHRyYWluX3BtYC4KCmBgYHtyfQoKc2ltcGxlX3JlYyA8LXJlY2lwZSh0cmFpbl9wbSkgJT4lCiAgICB1cGRhdGVfcm9sZShldmVyeXRoaW5nKCksIG5ld19yb2xlID0gInByZWRpY3RvciIpJT4lCiAgICB1cGRhdGVfcm9sZSh2YWx1ZSwgbmV3X3JvbGUgPSAib3V0Y29tZSIpJT4lCiAgICB1cGRhdGVfcm9sZShpZCwgbmV3X3JvbGUgPSAiaWQgdmFyaWFibGUiKQoKc2ltcGxlX3JlYwoKYGBgCgpJZiB3ZSB3YW50IHRvIHRha2UgYSBsb29rIGF0IG91ciBmb3JtdWxhIGZyb20gb3VyIHJlY2lwZSB3ZSBjYW4gZG8gdXNlIHRoZSBgZm9ybXVsYSgpYCBmdW5jdGlvbiBvZiB0aGUgYHN0YXRzYCBwYWNrYWdlLgoKYGBge3J9CmZvcm11bGEoc2ltcGxlX3JlYykKYGBgCgpXZSBjYW4gYWxzbyB2aWV3IG91ciByZWNpcGUgaW4gbW9yZSBkZXRhaWwgdXNpbmcgdGhlIGJhc2UgYHN1bW1hcnkoKWAgZnVuY3Rpb24uCgpgYGB7cn0Kc3VtbWFyeShzaW1wbGVfcmVjKQpgYGAKCiMjIyMgTGlzdCB0aGUgcHJlcHJvY2Vzc2luZyBzdGVwcyB1c2luZyB0aGUgc3RlcCBmdW5jdGlvbnMgb2YgdGhlIGByZWNpcGVgIHBhY2thZ2UKClRoZSBvdGhlciB0aGluZyB0aGUgcmVjaXBlcyBwYWNrYWdlIGFsbG93cyBmb3IgaXMgc3BlY2lmeWluZyBwcmUtcHJvY2Vzc2luZyBzdGVwcyB1c2luZyBhIHZhcmlldHkgb2YgYHN0ZXAqKClgIGZ1bmN0aW9ucy4KCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjQwMHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwiTWFraW5nX2FfcmVjaXBlX3JlY2lwZXMyLnBuZyIpKQpgYGAKCgoqKlRoaXMgW2xpbmtdKGh0dHBzOi8vdGlkeW1vZGVscy5naXRodWIuaW8vcmVjaXBlcy9yZWZlcmVuY2UvaW5kZXguaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSBhbmQgdGhpcyBbbGlua10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3JlY2lwZXMvcmVjaXBlcy5wZGYpe3RhcmdldD0iX2JsYW5rIn0gc2hvdyB0aGUgbWFueSBvcHRpb25zIGZvciByZWNpcGUgc3RlcCBmdW5jdGlvbnMuKioKCjx1PlRoZXJlIGFyZSBzdGVwIGZ1bmN0aW9ucyBmb3IgYSB2YXJpZXR5IG9mIHB1cnBvc2VzOjwvdT4KCjEpIFsqKkltcHV0YXRpb24qKl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSW1wdXRhdGlvbl8oc3RhdGlzdGljcykpe3RhcmdldD0iX2JsYW5rIn0gIC0tIHdoaWNoIG1lYW5zIGZpbGxpbmcgaW4gbWlzc2luZyB2YWx1ZXMgYmFzZWQgb24gdGhlIGV4aXN0aW5nIGRhdGEgCjIpIFsqKlRyYW5zZm9ybWF0aW9uKipdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0RhdGFfdHJhbnNmb3JtYXRpb25fKHN0YXRpc3RpY3MpKXt0YXJnZXQ9Il9ibGFuayJ9ICAtLSB3aGljaCBtZWFucyBjaGFuZ2luZyBhbGwgdmFsdWVzIG9mIGEgdmFyaWFibGUgaW4gdGhlIHNhbWUgd2F5LCB0eXBpY2FsbHkgdG8gbWFrZSBpdCBtb3JlIG5vcm1hbCBvciBlYXNpZXIgdG8gaW50ZXJwcmV0KSAgCjMpIFsqKkRpc2NyZXRpemF0aW9uKipdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Rpc2NyZXRpemF0aW9uX29mX2NvbnRpbnVvdXNfZmVhdHVyZXMpIC0tIHdoaWNoIG1lYW5zIGNvbnZlcnRpbmcgY29udGludW91cyB2YWx1ZXMgaW50byBkaXNjcmV0ZSBvciBub21pbmFsIHZhbHVlcyAtIGJpbm5pbmcgZm9yIGV4YW1wbGUgdG8gcmVkdWNlIHRoZSBudW1iZXIgb2YgcG9zc2libGUgbGV2ZWxzKSAgKEhvd2V2ZXIgdGhpcyBpcyBnZW5lcmFsbHkgbm90IGFkdmlzYWJsZSEpCjQpIFsqKkVuY29kaW5nIC8gQ3JlYXRpbmcgRHVtbXkgVmFyaWFibGVzKipdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0R1bW15X3ZhcmlhYmxlXyhzdGF0aXN0aWNzKSkgLS0gd2hpY2ggbWVhbnMgY3JlYXRpbmcgYSBudW1lcmljIGNvZGUgZm9yIGNhdGVnb3JpY2FsIHZhcmlhYmxlcwpbKipNb3JlIG9uIER1bW15IFZhcmlhYmxlcyBhbmQgb25lIGhvdCBlbmNvZGluZyoqXShodHRwczovL21lZGl1bS5jb20vcC9iNTg0MGJlM2M0MWEvcmVzcG9uc2VzL3Nob3cpCjUpIFsqKkRhdGEgdHlwZSBjb252ZXJzaW9ucyoqXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvaGFibGFyL3ZpZ25ldHRlcy9jb252ZXJ0Lmh0bWwpIC0tIHdoaWNoIG1lYW5zIGNoYW5naW5nIGZyb20gaW50ZWdlciB0byBmYWN0b3Igb3IgbnVtZXJpYyB0byBkYXRlIGV0Yy4KNikgWyoqSW50ZXJhY3Rpb24qKl0oaHR0cHM6Ly9zdGF0aXN0aWNzYnlqaW0uY29tL3JlZ3Jlc3Npb24vaW50ZXJhY3Rpb24tZWZmZWN0cy8pIHRlcm0gYWRkaXRpb24gdG8gdGhlIG1vZGVsIC0tIHdoaWNoIG1lYW5zIHRoYXQgd2Ugd291bGQgYmUgbW9kZWxpbmcgZm9yIHByZWRpY3RvcnMgdGhhdCB3b3VsZCBpbmZsdWVuY2UgdGhlIGNhcGFjaXR5IG9mIGVhY2ggb3RoZXIgdG8gcHJlZGljdCB0aGUgb3V0Y29tZQo3KSBbKipOb3JtYWxpemF0aW9uKipdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL05vcm1hbGl6YXRpb25fKHN0YXRpc3RpY3MpKSAtLSB3aGljaCBtZWFucyBjZW50ZXJpbmcgYW5kIHNjYWxpbmcgdGhlIGRhdGEgdG8gYSBzaW1pbGFyIHJhbmdlIG9mIHZhbHVlcwo4KSBbKipEaW1lbnNpb25hbGl0eSBSZWR1Y3Rpb24vIFNpZ25hbCBFeHRyYWN0aW9uKipdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0RpbWVuc2lvbmFsaXR5X3JlZHVjdGlvbikgLS0gd2hpY2ggbWVhbnMgbWF0aGVtYXRpY2FsbHkgb2J0YWluaW5nIGEgbmV3IHNtYWxsZXIgc2V0IG9mIHZhcmlhYmxlcyB0aGF0IGNhcHR1cmUgdGhlIHZhcmlhdGlvbiBvciBzaWduYWwgaW4gdGhlIG9yaWdpbmFsIHZhcmlhYmxlcyAoZXguIFByaW5jaXBhbCBDb21wb25lbnQgQW5hbHlzaXMgYW5kIEluZGVwZW5kZW50IENvbXBvbmVudCBBbmFseXNpcykKOSkgKipGaWx0ZXJpbmcqKiAtLSBGaWx0ZXJpbmcgb3B0aW9ucyBmb3IgcmVtb3ZpbmcgdmFyaWFibGVzIChleC4gcmVtb3ZlIHZhcmlhYmxlcyB0aGF0IGFyZSBoaWdobHkgY29ycmVsYXRlZCB0byBvdGhlcnMgb3IgcmVtb3ZlIHZhcmlhYmxlcyB3aXRoIHZlcnkgbGl0dGxlIHZhcmlhbmNlIGFuZCB0aGVyZWZvcmUgbGlrZWx5IGxpdHRsZSBwcmVkaWN0aXZlIGNhcGFjaXR5KQoxMCkgWyoqUm93IG9wZXJhdGlvbnMqKl0oaHR0cHM6Ly90YXJ0YXJ1cy5vcmcvZ2FyZXRoL21hdGhzL0xpbmVhcl9BbGdlYnJhL3Jvd19vcGVyYXRpb25zLnBkZikgLS0gd2hpY2ggbWVhbnMgcGVyZm9ybWluZyBmdW5jdGlvbnMgb24gdGhlIHZhbHVlcyB3aXRoaW4gdGhlIHJvd3MgIChleC4gcmVhcnJhbmdpbmcsIGZpbHRlcmluZywgaW1wdXRpbmcpCjExKSAqKkNoZWNraW5nIGZ1bmN0aW9ucyoqIC0tIFNhbml0eSBjaGVja3MgdG8gbG9vayBmb3IgbWlzc2luZyB2YWx1ZXMsIHRvIGxvb2sgYXQgdGhlIHZhcmlhYmxlIGNsYXNzZXMgZXRjLgoKQWxsIG9mIHRoZSBzdGVwIGZ1bmN0aW9ucyBsb29rIGxpa2UgYHN0ZXBfKmAgZXhjZXB0IGZvciB0aGUgY2hlY2sgZnVuY3Rpb25zIHdoaWNoIGxvb2sgbGlrZSBgY2hlY2tfKmAuCgpUaGVyZSBhcmUgc2V2ZXJhbCB3YXlzIHRvIHNlbGVjdCB3aGF0IHZhcmlhYmxlcyB0byBhcHBseSBzdGVwcyB0bzogIAoxKSB0aWR5c2VsZWN0IG1ldGhvZHM6IGBjb250YWlucygpYCwgYG1hdGNoZXMoKWAsIGBzdGFydHNfd2l0aCgpYCwgYGVuZHNfd2l0aCgpYCwgYGV2ZXJ5dGhpbmcoKWAsIGBudW1fcmFuZ2UoKWAgIAoyKSBiYXNlZCBvbiB0aGUgdHlwZTogYGFsbF9ub21pbmFsKClgLCBgYWxsX251bWVyaWMoKWAgLCBgaGFzX3R5cGUoKWAgCjMpIGJhc2VkIG9uIHRoZSByb2xlOiBgYWxsX3ByZWRpY3RvcnMoKWAsIGBhbGxfb3V0Y29tZXMoKWAsIGBoYXNfcm9sZSgpYAo0KSBuYW1lIC0gdXNlIHRoZSBhY3R1YWwgbmFtZSBvZiB0aGUgdmFyaWFibGUvdmFyaWFibGVzIG9mIGludGVyZXN0ICAKCgpMZXQncyB0cnkgYWRkaW5nIHNvbWUgc3RlcHMgdG8gb3VyIHJlY2lwZS4KCldlIG1pZ2h0IGNvbnNpZGVyIGxvZyB0cmFuc2Zvcm1pbmcgb3VyIHBvcHVsYXRpb24gYW5kIGFyZWEgdmFyaWFibGVzICh0aGF0IGFyZW4ndCBkZW5zaXRpZXMpIC0gbGV0J3MgdGFrZSBhIGxvb2sgYXQgdGhlIHJhbmdlIG9mIHRoZXNlIHZhcmlhYmxlcy4KYGBge3J9CnBtICU+JQogIHNlbGVjdChtYXRjaGVzKCJfcG9wfF9hcmVhIikpICU+JQogIG1hcChyYW5nZSkKYGBgCldlIGNhbiBzZWUgdGhhdCB0aGUgcmFuZ2UgZm9yIGVhY2ggb2YgdGhlc2UgdmFyaWFibGVzIGlzIHF1aXRlIGxhcmdlLCB3ZSBjYW4gbG9nIHRyYW5zZm9ybSB0aGlzIGRhdGEgdXNpbmcgdGhlIGBzdGVwX2xvZygpYCBmdW5jdGlvbiBvZiB0aGUgYHJlY2lwZXNgIHBhY2thZ2UuCgpXZSB3b3VsZCBhbHNvIHdhbnQgdG8gcG90ZW50aWFsbHkgb25lIGhvdCBlbmNvZGUgc29tZSBvZiBvdXIgY2F0ZWdvcmljYWwgdmFyaWFibGVzIHNvIHRoYXQgdGhleSBjYW4gYmUgdXNlZCB3aXRoIGNlcnRhaW4gYWxnb3JpdGhtcy4gV2UgY2FuIGRvIHRoaXMgd2l0aCB0aGUgYHN0ZXBfZHVtbXkoKWAgZnVuY3Rpb24gYW5kIHRoZSBgb25lX2hvdCA9IFRSVUVgIGFyZ3VtZW50LiBPdXIgZmlwcyB2YXJpYWJsZSBpbmNsdWRlcyBhIG51bWVyaWMgY29kZSBmb3Igc3RhdGUgYW5kIGNvdW50eSAtIGFuZCB0aGVyZWZvcmUgaXMgZXNzZW50aWFsbHkgYSBwcm94eSBmb3IgY291bnR5LiAgU2luY2Ugd2UgYWxyZWFkeSBoYXZlIGNvdW50eSwgd2Ugd2lsbCBqdXN0IHVzZSBpdCBhbmQga2VlcCB0aGUgZmlwcyBpZCBhcyBhbm90aGVyIElEIHZhcmlhYmxlLgoKV2UgY2FuIHJlbW92ZSB0aGUgYGZpcHNgIHZhcmlhYmxlIGZyb20gdGhlIHByZWRpY3RvcnMgdXNpbmcgYHVwZGF0ZV9yb2xlKClgIHRvIG1ha2Ugc3VyZSB0aGF0IHRoZSByb2xlIGlzIG5vIGxvbmdlciBgInByZWRpY3RvciJgLiBXZSBjYW4gbWFrZSB0aGUgcm9sZSBhbnl0aGluZyB3ZSB3YW50IGFjdHVhbGx5LCBzbyB3ZSB3aWxsIGtlZXAgaXQgc29tZXRoaW5nIGlkZW50aWZpYWJsZS4KCldlIG1pZ2h0IGFsc28gd2FudCB0byByZW1vdmUgdmFyaWFibGVzIHRoYXQgYXBwZWFyIHRvIGJlIHJlZHVuZGFudCBhbmQgYXJlIGhpZ2hseSBjb3JyZWxhdGVkIHdpdGggb3RoZXJzLCBhcyB3ZSBrbm93IGZyb20gb3VyIGV4cGxvcmF0b3J5IGRhdGEgYW5hbHlzaXMgdGhhdCBtYW55IG9mIG91ciB2YXJpYWJsZXMgYXJlIGNvcnJlbGF0ZWQgd2l0aCBvbmUgYW5vdGhlci4gV2UgY2FuIGRvIHRoaXMgdXNpbmcgdGhlIGBzdGVwX2NvcnIoKWAgZnVuY3Rpb24uCgpJdCBpcyBhbHNvIGEgZ29vZCBpZGVhIHRvIHJlbW92ZSB2YXJpYWJsZXMgd2l0aCBuZWFyLXplcm8gdmFyaWFuY2UsIHdoaWNoIGNhbiBiZSBkb25lIHdpdGggdGhlIGBzdGVwX256digpYCBmdW5jdGlvbi4gVmFyaWFibGVzIGhhdmUgbG93IHZhcmlhbmNlIGlmIGFsbCB0aGUgdmFsdWVzIGFyZSB2ZXJ5IHNpbWlsYXIsIHRoZSB2YWx1ZXMgYXJlIHZlcnkgc3BhcnNlLCBvciBpZiB0aGV5IGFyZSBoaWdobHkgaW1iYWxhbmNlZC4gCgpFeGFtcGxlcyB3aGVyZSB5b3UgbWlnaHQgaGF2ZSBuZWFyLXplcm8gdmFyaWFuY2UgdmFyaWFibGVzIGluY2x1ZGU6ICMjIyBJIFN0cnVnZ2xlZCB0byBmaW5kIGxpbmtzIGZvciB0aGlzLi4uIHRvIGJhY2sgdXAgbXkgc3RhdGVtZW50cyMjIwoKMSkgKipTaW1pbGFyIFZhbHVlcyoqIC0gSWYgdGhlIHBvcHVsYXRpb24gZGVuc2l0eSB3YXMgbmVhcmx5IHRoZSBzYW1lIGZvciBldmVyeSB6Y3RhIHRoYXQgY29udGFpbmVkIGEgbW9uaXRvciwgdGhlbiBrbm93aW5nIHRoZSBwb3B1bGF0aW9uIGRlbnNpdHkgbmVhciBvdXIgbW9uaXRvcndvdWxkIGNvbnRyaWJ1dGUgbGl0dGxlIHRvIG91ciBtb2RlbCBpbiBhc3Npc3RpbmcgdXMgdG8gcHJlZGljdCBtb25pdG9yIGFpciBwb2xsdXRpb24gdmFsdWVzLiAKMikgKipTcGFyc2UgRGF0YSoqIC0gSWYgYWxsIG9mIHRoZSBtb25pdG9ycyB3ZXJlIGluIGxvY2F0aW9ucyB3aGVyZSB0aGUgcG9wdWxhdGlvbnMgZGlkIG5vdCBhdHRlbmQgZ3JhZHVhdGUgc2Nob29sLCB0aGVuIHRoZXNlIHZhbHVlcyB3b3VsZCBtb3N0bHkgYmUgemVybywgYWdhaW4gdGhpcyB3b3VsZCBkbyB2ZXJ5IGxpdHRsZSB0byBoZWxwIHVzIGRpc3Rpbmd1aXNoIG91ciBhaXIgcG9sbHV0aW9uIG1vbml0b3JzLldoZW4gbWFueSBvZiB0aGUgdmFsdWVzIGFyZSB6ZXJvIHRoaXMgaXMgYWxzbyBjYWxsZWQgc3BhcnNlIGRhdGEuICAKMykgKipJbWJhbGFuY2VkIERhdGEqKiBJZiBuZWFybHkgYWxsIG9mIHRoZSBtb25pdG9ycyB3ZXJlIGxvY2F0ZWQgaW4gb25lIHBhcnRpY3VsYXIgc3RhdGUsIGFuZCBhbGwgdGhlIG90aGVycyBvbmx5IGhhZCBvbmUgbW9uaXRvciBlYWNoLCB0aGVuIHRoZSByZWFsIHByZWRpY3RpdmUgdmFsdWUgd291bGQgc2ltcGx5IGJlIGluIGtub3dpbmcgaWYgYSBtb25pdG9yIGlzIGxvY2F0ZWQgaW4gdGhhdCBwYXJ0aWN1bGFyIHN0YXRlIG9yIG5vdC4gSW4gdGhpcyBjYXNlIHdlIGRvbid0IHdhbnQgdG8gcmVtb3ZlIG91ciB2YXJpYWJsZSwgd2UganVzdCB3YW50IHRvIHNpbXBsaWZ5IGl0LgoKKipJdCBpcyBpbXBvcnRhbnQgdG8gYWRkIHRoZSBzdGVwcyB0byB0aGUgcmVjaXBlIGluIGFuIG9yZGVyIHRoYXQgbWFrZXMgc2Vuc2UganVzdCBsaWtlIHdpdGggYSBjb29raW5nIHJlY2lwZS4qKgoKVGh1cyBmaXJzdCB3ZSBhcmUgZ29pbmcgdG8gY3JlYXRlIG51bWVyaWMgdmFsdWVzIGZvciBvdXIgY2F0ZWdvcmljYWwgdmFyaWFibGVzLCB0aGVuIHdlIHdpbGwgbG9vayBhdCBjb3JyZWxhdGlvbiBhbmQgbmVhci16ZXJvIHZhcmlhbmNlLiBXZSBkb24ndCB3YW50IHRvIHJlbW92ZSBzb21lIG9mIG91ciB2YXJpYWJsZXMsIGxpa2UgdGhlIENNQVEgYW5kIGFvZCB2YXJpYWJsZXMgc28gd2UgY2FuIG1ha2Ugc3VyZSB0aGV5IGFyZSBrZXB0IGluIHRoZSBtb2RlbCBieSBleGNsdWRpbmcgdGhlbSBmcm9tIHRob3NlIHN0ZXBzLiBJZiB3ZSBzcGVjaWZpY2FsbHkgd2FudGVkIHRvIHJlbW92ZSBhIHByZWRpY3RvciB3ZSBjb3VsZCB1c2UgYHN0ZXBfcm0oKWAuCgpgYGB7cn0Kc2ltcGxlX3JlYyAlPD4lCiAgdXBkYXRlX3JvbGUoImZpcHMiLCBuZXdfcm9sZSA9ICJjb3VudHkgaWQiKSAlPiUKIyBjcmVhdGUgbnVtZXJpYyBkdW1teSB2YXJpYWJsZXMgdG8gZW5jb2RlIGZvciBjYXRlZ29yaWNhbCB2YXJpYWJsZXMKICBzdGVwX2R1bW15KHN0YXRlLCBjb3VudHksIGNpdHksIHpjdGEsIG9uZV9ob3QgPSBUUlVFKSAlPiUKICAjIGlkZW50aWZ5IGFuZCByZW9tdmUgYWxsIGNvcnJlbGF0ZWQgcHJlZGljdG9ycyAobm93IHRoYXQgdGhleSBhcmUgbnVtZXJpYykKICAgc3RlcF9jb3JyKGFsbF9wcmVkaWN0b3JzKCksIC0gQ01BUSwgLSBhb2QpJT4lCiAgIyBpZGVudGlmeSB2YXJpYWJsZXMgd2l0aCBuZWFyIHplcm8gdmFyaWFuY2UgYW5kIHJlbW92ZQogIHN0ZXBfbnp2KGFsbF9wcmVkaWN0b3JzKCksIC0gQ01BUSwgLSBhb2QpCiAgCnNpbXBsZV9yZWMKCmBgYAoKCgojIyMgT1BUSU9OQUwoYnV0IHJlY29tbWVuZGVkKTogUnVubmluZyB0aGUgcHJlcHJvY2Vzc2luZyAodG8gc2VlIGl0KQoKVGhlIG5leHQgbWFqb3IgZnVuY3Rpb24gb2YgdGhlIGByZWNpcGVzYCBwYWNrYWdlIGlzIGBwcmVwKClgLgoKVGhpcyBmdW5jdGlvbiB1cGRhdGVzIHRoZSByZWNpcGUgb2JqZWN0IGJhc2VkIG9uIHRoZSB0cmFpbmluZyBkYXRhLiBJdCBlc3RpbWF0ZXMgcGFyYW1ldGVycyAoZXN0aW1hdGluZyB0aGUgcmVxdWlyZWQgcXVhbnRpdGllcyBhbmQgc3RhdGlzdGljcyByZXF1aXJlZCBieSB0aGUgc3RlcHMgZm9yIHRoZSB2YXJpYWJsZXMpIGZvciBwcmVwcm9jZXNzaW5nIGFuZCAgdXBkYXRlcyB0aGUgbW9kZWwgdGVybXMsIGFzIHNvbWUgb2YgdGhlIHByZWRpY3RvcnMgbWF5IGJlIHJlbW92ZWQsIHRoaXMgYWxsb3dzIHRoZSByZWNpcGUgdG8gYmUgcmVhZHkgdG8gdXNlIG9uIG90aGVyIGRhdGFzZXRzLiBJdCBkb2Vzbid0IG5lY2Vzc2FyaWx5IGFjdHVhbGx5IGV4ZWN1dGUgdGhlIHByZXByb2Nlc3NpbmcgaXRzZWxmLCBob3dldmVyIHdlIHdpbGwgc3BlY2lmeSBpbiBhcmd1bWVudCBmb3IgaXQgdG8gZG8gdGhpcyBzbyB0aGF0IHdlIGNhbiB0YWtlIGEgbG9vayBhdCB0aGUgcHJlcHJvY2Vzc2VkIGRhdGEuCgpUaGVyZSBhcmUgc29tZSBpbXBvcnRhbnQgYXJndW1lbnRzIHRvIGtub3cgYWJvdXQ6CjEpIHRyYWluaW5nIC0geW91IG11c3Qgc3VwcGx5IGEgdHJhaW5pbmcgZGF0YSBzZXQgdG8gZXN0aW1hdGUgcGFyYW1ldGVycyBmb3IgcHJlcHJvY2Vzc2luZyBvcGVyYXRpb25zIChyZWNpcGUgc3RlcHMpIC0gdGhpcyBtYXkgYWxyZWFkeSBiZSBpbmNsdWRlZCBpbiB5b3VyIHJlY2lwZSAtIGFzIGlzIHRoZSBjYXNlIGZvciB1cwoyKSBmcmVzaCAtIGlmIFRSVUUgLSB3aWxsIHJldHJhaW4gYW5kIGVzdGltYXRlIHBhcmFtZXRlcnMgZm9yIGFueSBwcmV2aW91cyBzdGVwcyB0aGF0IHdlcmUgYWxyZWFkeSBwcmVwcGVkIGlmIHlvdSBhZGQgbW9yZSBzdGVwcyB0byB0aGUgcmVjaXBlCjMpIHZlcmJvc2UgLSBpZiBgVFJVRWAgc2hvd3MgdGhlIHByb2dyZXNzIGFzIHRoZSBzdGVwcyBhcmUgZXZhbHVhdGVkIGFuZCB0aGUgc2l6ZSBvZiB0aGUgcHJlcHJvY2Vzc2VkIHRyYWluaW5nIHNldAo0KSByZXRhaW4gLSBpZiBgVFJVRWAgdGhlbiB0aGUgcHJlcHJvY2Vzc2VkIHRyYWluaW5nIHNldCB3aWxsIGJlIHNhdmVkIHdpdGhpbiB0aGUgcmVjaXBlIChhcyB0ZW1wbGF0ZSkuIFRoaXMgaXMgZ29vZCBpZiB5b3UgYXJlIGxpa2VseSB0byBhZGQgbW9yZSBzdGVwcyBhbmQgZG9uJ3Qgd2FudCB0byByZXJ1biB0aGUgYHByZXAoKWAgb24gdGhlIHByZXZpb3VzIHN0ZXBzLiBIb3dldmVyIHRoaXMgY2FuIG1ha2UgdGhlIHJlY2lwZSBzaXplIGxhcmdlLiBUaGlzIGlzIG5lY2Vzc2FyeSBpZiB5b3Ugd2FudCB0byBhY3R1YWxseSBsb29rIGF0IHRoZSBwcmVwcm9jZXNzZWQgZGF0YS4KCgpgYGB7cn0KcHJlcHBlZF9yZWMgPC0gcHJlcChzaW1wbGVfcmVjLCB2ZXJib3NlID0gVFJVRSwgcmV0YWluID0gVFJVRSApCm5hbWVzKHByZXBwZWRfcmVjKQpgYGAKClRoZXJlIGFyZSBhbHNvIGxvdHMgb2YgdXNlZnVsIHRoaW5ncyB0byBjaGVja291dCBpbiB0aGUgb3V0cHV0IG9mIGBwcmVwKClgLgpZb3UgY2FuIHNlZToKMSkgdGhlIGBzdGVwc2AgdGhhdCB3ZXJlIHJ1biAgCjIpIHRoZSB2YXJpYWJsZSBpbmZvIChgdmFyX2luZm9gKSAgCjMpIHRoZSBtb2RlbCBgdGVybV9pbmZvYAo0KSB0aGUgbmV3IGBsZXZlbHNgIG9mIHRoZSB2YXJpYWJsZXMgCjUpIHRoZSBvcmlnaW5hbCBsZXZlbHMgb2YgdGhlIHZhcmlhYmxlcyBgb3JpZ19sdmxzYCAgIAo2KSBpbmZvIGFib3V0IHRoZSB0cmFpbmluZyBkYXRhIHNldCBzaXplIGFuZCBjb21wbGV0ZW5lc3MgKGB0cl9pbmZvYCkKCk5vdGU6ICBZb3UgbWF5IHNlZSB0aGUgYHByZXAucmVjaXBlKClgIGZ1bmN0aW9uIGluIG1hdGVyaWFsIHRoYXQgeW91IHJlYWQgYWJvdXQgdGhlIGByZWNpcGVzYCBwYWNrYWdlLiBUaGlzIGlzIHJlZmVycmluZyB0byB0aGUgYHByZXAoKWAgZnVuY3Rpb24gb2YgdGhlIGByZWNpcGVzYCBwYWNrYWdlLgoKIyMjIyBFeHRyYWN0aW5nIHRoZSBwcmVwcm9jZXNzZWQgdHJhaW5pbmcgZGF0YQoKYGBge3IsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iNDAwcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJ0cmFpbmluZ19wcmVwcm9jZXNzaW5nX3JlY2lwZXMzLnBuZyIpKQpgYGAKClNpbmNlIHdlIHJldGFpbmVkIG91ciBwcmVwcm9jZXNzZWQgdHJhaW5pbmcgZGF0YSwgd2UgY2FuIHRha2UgYSBsb29rIGF0IGl0IGxpa2UgYnkgdXNpbmcgdGhlIGBqdWljZSgpYCBmdW5jdGlvbiBvZiB0aGUgYHJlY2lwZXNgIHBhY2thZ2UgbGlrZSB0aGlzOgoKIyMjIyB7LnNjcm9sbGFibGUgfQpgYGB7cn0KIyBTY3JvbGwgdGhlcm91Z2ggdGhlIG91dHB1dCEKanVpY2VkX3RyYWluPC0ganVpY2UocHJlcHBlZF9yZWMpCmdsaW1wc2UoanVpY2VkX3RyYWluKQpgYGAKIyMjIwoKCkZvciBlYXN5IGNvbXBhcmlzb24gc2FrZSAtIGhlcmUgaXMgb3VyIG9yaWdpbmFsIGRhdGE6CiMjIyMgey5zY3JvbGxhYmxlIH0KYGBge3J9CiMgU2Nyb2xsIHRoZXJvdWdoIHRoZSBvdXRwdXQhCmdsaW1wc2UocG0pCmBgYAojIyMjCgpOb3RpY2UgaG93IHdlIG9ubHkgaGF2ZSAzNiB2YXJpYWJsZXMgbm93IGluc3RlYWQgb2YgNTAhIFR3byBvZiB0aGVzZSBhcmUgb3VyIElEIHZhcmlhYmxlcyAoYGZpcHNgIGFuZCB0aGUgYWN0dWFsIG1vbml0b3IgSUQgKGBpZGApKSBhbmQgb25lIGlzIG91ciBvdXRjb21lIChgdmFsdWVgKS4gVGh1cyB3ZSBvbmx5IGhhdmUgMzMgcHJlZGljdG9ycyBub3cuIFdlIGNhbiBhbHNvIHNlZSB0aGF0IHZhcmlhYmxlcyB0aGF0IHdlIG5vIGxvbmdlciBoYXZlIGFueSBjYXRlZ29yaWNhbCB2YXJpYWJsZXMuIFZhcmlhYmxlcyBsaWtlIGBzdGF0ZWAgYXJlIGdvbmUgYW5kIG9ubHkgYHN0YXRlX0NhbGlmb3JuaWFgIHJlbWFpbnMgYXMgaXQgd2FzIHRoZSBvbmx5IHN0YXRlIGlkZW50aXR5IHRvIGhhdmUgbm9uemVybyB2YXJpYW5jZS4gIFdlIGNhbiBzZWUgdGhhdCBDYWxpZm9ybmlhIGhhZCB0aGUgbGFyZ2VzdCBudW1iZXIgb2YgbW9uaXRvcnMgY29tcGFyZWQgdG8gdGhlIG90aGVyIHN0YXRlcy4gV2UgY2FuIGFsc28gc2VlIHRoYXQgdGhlcmUgd2VyZSBtb3JlIG1vbml0b3JzIGxpc3RlZCBhcyBgIk5vdCBpbiBhIGNpdHkiYCB0aGFuIGFueSBjaXR5LiAKCiMjIyMgey5zY3JvbGxhYmxlIH0KYGBge3J9CnBtICU+JSBjb3VudChzdGF0ZSkKcG0gJT4lIGNvdW50KGNpdHkpCmBgYAojIyMjCgoqKk5vdGUqKjogIFJlY2FsbCB0aGF0IHlvdSBtdXN0IHNwZWNpZnkgYHJldGFpbiA9IFRSVUVgIGFyZ3VtZW50IG9mIHRoZSBgcHJlcCgpYCBmdW5jdGlvbiB0byB1c2UgYGp1aWNlKClgLgoKIyMjIyBFeHRyYWN0aW5nIHRoZSBwcmVwcm9jZXNzZWQgdGVzdGluZyBkYXRhCgpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI0MDBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsInRlc3RpbmdfcHJlcHJvY2Vzc2luZ19yZWNpcGVzNC5wbmciKSkKYGBgCgpBY2Nyb2RpbmcgdG8gdGhlIHRpZHltb2RlbHMgZG9jdW1lbnRhdGlvbjoKCj4gYGJha2UoKWAgdGFrZXMgYSB0cmFpbmVkIHJlY2lwZSBhbmQgYXBwbGllcyB0aGUgb3BlcmF0aW9ucyB0byBhIGRhdGEgc2V0IHRvIGNyZWF0ZSBhIGRlc2lnbiBtYXRyaXguCiBmb3IgZXhhbXBsZTogIGl0IGFwcGxpZXMgdGhlIGNlbnRlcmluZyB0byBuZXcgZGF0YSBzZXRzIHVzaW5nIHRoZXNlIG1lYW5zIHVzZWQgdG8gY3JlYXRlIHRoZSByZWNpcGUKCgpOT1RFIHRoaXMgbmV4dCBzZWN0aW9uIGNvdWxkIGJlIHJlbW92ZWQgaWYgaXQgaXMgY29uZnVzaW5nLi4uIGFuZCB3ZSB3b3VsZCB0aGVyZWZvcmUgdXBkYXRlIHRoZSBvcmdpbmFsIHNpbXBsZV9yZWMgcmVjaXBlLiBCdXQgaXQgc2hvd3Mgd2hhdCBJIGhhZCBkaWZmaWN1bHR5IHdpdGggLSB0aGUgbmV3IGxldmVscyBpbiB0ZXN0aW5nIGRhdGEuLgoKSWYgeW91IHdhbnRlZCB0byBsb29rIGF0IHRoZSBwcmVwcm9jZXNzZWQgdGVzdGluZyBkYXRhIHlvdSB3b3VsZCB1c2UgdGhlIGBiYWtlKClgIGZ1bmN0aW9uIG9mIHRoZSBgcmVjaXBlc2AgcGFja2FnZS4KKFlvdSBnZW5lcmFsbHkgd2FudCB0byBsZWF2ZSB5b3VyIHRlc3RpbmcgZGF0YSBhbG9uZSwgYnV0IGl0IGlzIGdvb2QgdG8gbG9vayBmb3IgaXNzdWVzIGxpa2UgdGhlIGludHJvZHVjdGlvbiBvZiBOQSB2YWx1ZXMpLgoKIyMjIyB7LnNjcm9sbGFibGUgfQpgYGB7cix9CiMgU2Nyb2xsIHRoZXJvdWdoIHRoZSBvdXRwdXQhCmJha2VkX3Rlc3RfcG0gPC0gcmVjaXBlczo6YmFrZShwcmVwcGVkX3JlYywgbmV3X2RhdGEgPSB0ZXN0X3BtKQpnbGltcHNlKGJha2VkX3Rlc3RfcG0gKQpgYGAKIyMjIwoKCk5vdGljZSB0aGF0IG91ciBgY2l0eV9Ob3QuaW4uYS5jaXR5YCB2YXJpYWJsZSBzZWVtcyB0byBiZSBOQSB2YWx1ZXMuIFdoeSBtaWdodCB0aGF0IGJlPwoKQWghIFBlcnBoYXMgaXQgaXMgYmVjYXVzZSBzb21lIG9mIG91ciBsZXZlbHMgd2VyZSBub3QgcHJldmlvdXNseSBzZWVuIGluIHRoZSB0cmFpbmluZyBzZXQhCgpMZXQncyB0YWtlIGEgbG9vayB1c2luZyB0aGUgW3NldCBvcGVyYXRpb25zXShodHRwczovL3d3dy5wcm9iYWJpbGl0eWNvdXJzZS5jb20vY2hhcHRlcjEvMV8yXzJfc2V0X29wZXJhdGlvbnMucGhwKSBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlLiBXZSBjYW4gdGFrZSBhIGxvb2sgYXQgY2l0aWVzIHRoYXQgd2VyZSBkaWZmZXJlbnQgYmV0d2VlbiB0aGUgdGVzdCBhbmQgdHJhaW5pbmcgc2V0LgoKYGBge3J9CnRyYWluY2l0aWVzIDwtIHRyYWluX3BtICU+JSBkaXN0aW5jdChjaXR5KQp0ZXN0Y2l0aWVzIDwtIHRlc3RfcG0gJT4lIGRpc3RpbmN0KGNpdHkpCgojZ2V0IHRoZSBudW1iZXIgb2YgY2l0aWVzIHRoYXQgd2VyZSBkaWZmZXJlbnQKZGltKGRwbHlyOjpzZXRkaWZmKHRyYWluY2l0aWVzLCB0ZXN0Y2l0aWVzKSkKCiNnZXQgdGhlIG51bWJlciBvZiBjaXRpZXMgdGhhdCBvdmVybGFwcGVkCmRpbShkcGx5cjo6aW50ZXJzZWN0KHRyYWluY2l0aWVzLCB0ZXN0Y2l0aWVzKSkKYGBgCgpJbmRlZWQsIHRoZXJlIGFyZSBsb3RzIG9mIGRpZmZlcmVudCBjaXRpZXMgaW4gb3VyIHRlc3QgZGF0YSB0aGF0IGFyZSBub3QgaW4gb3VyIHRyYWluaW5nIGRhdGEhCgpNYXliZSByZW1vdmUgdGhpcz86IFRodXMgd2UgbmVlZCB0byB1cGRhdGUgb3VyIG9yaWdpbmFsIHJlY2lwZSB0byBpbmNsdWRlIGEgdmVyeSBpbXBvcnRhbnQgc3RlcCBmdW5jdGlvbiBjYWxsZWQgYHN0ZXBfbm92ZWwoKWAgdGhpcyBoZWxwcyBpbiBjYXNlcyBsaWtlIHRoaXMgd2VyZSB0aGVyZSBhcmUgbmV3IGZhY3RvcnMgaW4gb3VyIHRlc3Rpbmcgc2V0IHRoYXQgd2VyZSBub3QgaW4gb3VyIHRyYWluaW5nIHNldC4gSXQgaXMgYSBnb29kIGlkZWEgdG8gaW5jbHVkZSB0aGlzIGluIG1vc3Qgb2YgeW91ciByZWNpcGVzIHdoZXJlIHlvdSBoYXZlIGEgY2F0ZWdvcmljYWwgdmFyaWFibGVzIHdpdGggbWFueSBkaXN0aW5jdCB2YWx1ZXMuIFRoaXMgc3RlcCBuZWVkcyB0byBjb21lIGJlZm9yZSB3ZSBjcmVhdGUgZHVtbXkgdmFyaWFibGVzLiBIb3dldmVyLCB3ZSBhcmUgYWxzbyBjcmVhdGluZyBhIGR1bW15IHZhcmlhYmxlIGZyb20gdGhpcywgd2hpY2ggc3RpbGwgcmVzdWx0cyBpbiBhIHByb2JsZW0uIAoKCkxldCdzIG1vZGlmeSB0aGUgY2l0eSB2YXJpYWJsZSB0byBiZSB2YWx1ZXMgb2YgYGluIGEgY2l0eWAgb3IgYG5vdCBpbiBhIGNpdHlgIHVzaW5nIHRoZSBgaWZfZWxzZSgpYCBmdW5jdGlvbiBvZiBgZHBseXJgLiBBbHRlcm5hdGl2ZWx5IHlvdSBjb3VsZCBjcmVhdGUgYSBbY3VzdG9tIHN0ZXAgZnVuY3Rpb25dKGh0dHBzOi8vcmVjaXBlcy50aWR5bW9kZWxzLm9yZy9hcnRpY2xlcy9DdXN0b21fU3RlcHMuaHRtbCkgdG8gZG8gdGhpcyBhbmQgYWRkIHRoZSBzdGVwIGZ1bmN0aW9uIHRvIHlvdXIgcmVjaXBlLCBidXQgdGhhdCBpcyBiZXlvbmQgdGhlIHNjb3BlIG9mIHRoaXMgY2FzZSBzdHVkeS4gCgpXZSBuZWVkIHRvIGNyZWF0ZSBhIG5ldyByZWNpcGUgdG8gbW92ZSBmb3J3YXJkLCBhcyB0aGUgbGV2ZWxzIG9mIG91ciB2YXJpYWJsZXMgYXJlIGVzdGFibGlzaGVkIHRoZW4uIFdlIHdvdWxkIGFsc28gcG90ZW50aWFsbHkgaGF2ZSB0aGlzIGlzc3VlIGZvciBzdGF0ZSBhbmQgY291bnR5LiBTbyBsZXQncyBhbHNvIGRvIGEgc2ltaWxhciB0aGluZyBmb3IgYHN0YXRlYC4gVGhlIGBjb3VudHlgIHZhcmlhYmxlcyBhcHBlYXJzIHRvIGdldCBkcm9wcGVkIGR1ZSB0byBlaXRoZXIgY29ycmVsYXRpb24gb3IgbmVhciB6ZXJvIHZhcmlhbmNlLiBJdCBpcyBsaWtlbHkgZHVlIHRvIG5lYXIgemVybyB2YXJpYW5jZSBiZWN1YXNlIHRoaXMgaXMgdGhlIG1vcmUgZ3JhbnVsYXIgb2YgdGhlc2UgZ2VvZ3JhcGhpYyBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgYW5kIGxpa2VseSBzcGFyc2UuCgoKYGBge3J9Cgp0cmFpbl9wbVtbImNpdHkiXV0gPC0gaWZfZWxzZSgKICB0cmFpbl9wbVtbImNpdHkiXV0gPT0gIk5vdCBpbiBhIGNpdHkiLCAKICB0cnVlID0gIk5vdCBpbiBhIGNpdHkiLCBmYWxzZSA9ICJJbiBhIGNpdHkiKQoKdGVzdF9wbVtbImNpdHkiXV0gPC0gaWZfZWxzZSgKICB0ZXN0X3BtW1siY2l0eSJdXSA9PSAiTm90IGluIGEgY2l0eSIsIAogIHRydWUgPSAiTm90IGluIGEgY2l0eSIsIGZhbHNlID0gIkluIGEgY2l0eSIpCgp0cmFpbl9wbVtbInN0YXRlIl1dIDwtIGlmX2Vsc2UoCiAgdHJhaW5fcG1bWyJzdGF0ZSJdXSA9PSAiQ2FsaWZvcm5pYSIsIAogIHRydWUgPSAiQ2FsaWZvcm5pYSIsIGZhbHNlID0gIk5vdCBDYWxpZm9ybmlhIikKCnRlc3RfcG1bWyJzdGF0ZSJdXSA8LSBpZl9lbHNlKAogIHRlc3RfcG1bWyJzdGF0ZSJdXSA9PSAiQ2FsaWZvcm5pYSIsIAogIHRydWUgPSAiQ2FsaWZvcm5pYSIsIGZhbHNlID0gIk5vdCBDYWxpZm9ybmlhIikKICAKbm92ZWxfcmVjIDwtcmVjaXBlKHRyYWluX3BtKSAlPiUKICAgIHVwZGF0ZV9yb2xlKGV2ZXJ5dGhpbmcoKSwgbmV3X3JvbGUgPSAicHJlZGljdG9yIiklPiUKICAgIHVwZGF0ZV9yb2xlKHZhbHVlLCBuZXdfcm9sZSA9ICJvdXRjb21lIiklPiUKICAgIHVwZGF0ZV9yb2xlKGlkLCBuZXdfcm9sZSA9ICJpZCB2YXJpYWJsZSIpJT4lCiAgICB1cGRhdGVfcm9sZSgiZmlwcyIsIG5ld19yb2xlID0gImNvdW50eSBpZCIpJT4lCiMgY3JlYXRlIG51bWVyaWMgZHVtbXkgdmFyaWFibGVzIHRvIGVuY29kZSBmb3IgY2F0ZWdvcmljYWwgdmFyaWFibGVzCiAgICBzdGVwX2R1bW15KHN0YXRlLCBjb3VudHksIGNpdHksIHpjdGEsIG9uZV9ob3QgPSBUUlVFKSAlPiUKIyBpZGVudGlmeSBhbmQgcmVvbXZlIGFsbCBjb3JyZWxhdGVkIHByZWRpY3RvcnMgKG5vdyB0aGF0IHRoZXkgYXJlIG51bWVyaWMpCiAgIHN0ZXBfY29ycihhbGxfbnVtZXJpYygpKSU+JQojIGlkZW50aWZ5IHZhcmlhYmxlcyB3aXRoIG5lYXIgemVybyB2YXJpYW5jZSBhbmQgcmVtb3ZlCiAgc3RlcF9uenYoYWxsX251bWVyaWMoKSkgIyAKIApgYGAKCk5vdyBsZXQncyByZXRyYWluIG91ciB0cmFpbmluZyBkYXRhIGFuZCB0cnkgYmFraW5nIG91ciB0ZXN0IGRhdGE6CgpgYGB7cn0KcHJlcHBlZF9yZWMgPC0gcHJlcChub3ZlbF9yZWMsIHZlcmJvc2UgPSBUUlVFLCByZXRhaW4gPSBUUlVFKQpgYGAKCgojIyMjIHsuc2Nyb2xsYWJsZSB9CmBgYHtyfQojIFNjcm9sbCB0aGVyb3VnaCB0aGUgb3V0cHV0IQpqdWljZWRfdHJhaW48LSBqdWljZShwcmVwcGVkX3JlYykKZ2xpbXBzZShqdWljZWRfdHJhaW4pCmBgYAoKIyMjIwoKTm90aWNlLCBpdCBsb29rcyBsaWtlIHdlIGdhaW5lZCB0aGUgYGxvZ19wcmlzZWNfbGVuZ3RoXzI1MDAwYCBiYWNrIHdpdGggdGhpcyByZWNpcGUgdXNpbmcgdGhlIGRhdGEgd2l0aCBvdXIgY2hhbmdlcyB0byBgc3RhdGVgIGFuZCBgY2l0eWAuCgpgYGB7cn0KYmFrZWRfdGVzdF9wbTwtIHJlY2lwZXM6OmJha2UocHJlcHBlZF9yZWMsIG5ld19kYXRhID0gdGVzdF9wbSkKZ2xpbXBzZShiYWtlZF90ZXN0X3BtKQpgYGAKCkdyZWF0IG5vdyB3ZSBubyBsb25nZXIgaGF2ZSBOQSB2YWx1ZXMhIDopCgoKTm90ZTogaWYgeW91IHVzZSB0aGUgc2tpcCBvcHRpb24gZm9yIHNvbWUgb2YgdGhlIHByZXByb2Nlc3Npbmcgc3RlcHMsIGJlIGNhcmVmdWwuIGBqdWljZSgpYCB3aWxsIHNob3cgYWxsIG9mIHRoZSByZXN1bHRzIGlnbm9yaW5nIGBza2lwID0gVFJVRWAuIGBiYWtlKClgIHdpbGwgbm90IG5lY2Vzc2FyaWx5IGNvbmR1Y3QgdGhlc2Ugc3RlcHMgb24gdGhlIG5ldyBkYXRhLiAKCgojIyMgU3BlY2lmeWluZyB0aGUgTW9kZWwKClNvIGZhciB3ZSBoYXZlIHVzZWQgYHJzYW1wbGVgIHRvIHNwbGl0IHRoZSBkYXRhIGFuZCBgcmVjaXBlc2AgdG8gYXNzaWduIHZhcmlhYmxlIGFuZCB0byBzcGVjaWZ5IGFuZCBwcmVwIG91ciBwcmVwcm9jZXNzaW5nIChhcyB3ZWxsIGFzIHRvIG9wdGlvbmFsbHkgZXh0cmFjdCB0aGUgcHJlcHJvY2Vzc2VkIGRhdGEpLgoKV2Ugd2lsbCBub3cgdXNlIHRoZSBgcGFyc25pcGAgcGFja2FnZSAod2hpY2ggaXMgc2ltaWxhciB0byB0aGUgcHJldmlvdXMgYGNhcmV0YCBwYWNrYWdlIC0gYW5kIGhlbmNlIHdoeSBpdCBpcyBuYW1lZCBhZnRlciB0aGUgdmVnZXRhYmxlKSB0byBzcGVjaWZ5IG91ciBtb2RlbC4KClRoZXJlIGFyZSBmb3VyIGFzcGVjdHMgdG8gZGVmaW5lIGFib3V0IG91ciBtb2RlbDogIAoxKSB0aGUgKip0eXBlKiogb2YgbW9kZWwgKHVzaW5nIHNwZWNpZmljIGZ1bnRpb25zIGluIHBhcnNuaXAgbGlrZSBgcmFuZF9mb3Jlc3QoKWAsIGBsb2dpc3RpY19yZWcoKWAgZXRjLikgIAoyKSB0aGUgKiptb2RlKiogb2YgbGVhcm5pbmcgLSBjbGFzc2lmaWNhdGlvbiBvciByZWdyZXNzaW9uICh1c2luZyB0aGUgYHNldF9tb2RlKClgIGZ1bmN0aW9uKSAgCjMpIHRoZSBwYWNrYWdlIG9yICoqZW5naW5lKiogdGhhdCB3ZSB3aWxsIHVzZSB0byBpbXBsZW1lbnQgdGhlIHR5cGUgb2YgbW9kZWwgc2VsZWN0ZWQgKHVzaW5nIHRoZSBgc2V0X2VuZ2luZSgpYCBmdW5jdGlvbikgIAo0KSBhbnkgKiphcmd1bWVudHMqKiBuZWNlc3NhcnkgZm9yIHRoZSBtb2RlbC9wYWNrYWdlIHNlbGVjdGVkICh1c2luZyB0aGUgYHNldF9hcmdzKClgZnVuY3Rpb24gLSAgZm9yIGV4YW1wbGUgdGhlIGBtdHJ5ID1gIGFyZ3VtZW50IGZvciByYW5kb20gZm9yZXN0IHdoaWNoIGlzIHRoZSBudW1iZXIgb2YgdmFyaWFibGVzIHRvIGJlIHVzZWQgYXMgb3B0aW9ucyBmb3Igc3BsaXR0aW5nIGF0IGVhY2ggdHJlZSBub2RlKSAgCgpXZSBhcmUgZ29pbmcgdG8gc3RhcnQgb3VyIGFuYWx5c2lzIHdpdGggYSBsaW5lYXIgcmVncmVzc2lvbiBidXQgd2Ugd2lsbCBkZW1vbnN0cmF0ZSBob3cgd2UgY2FuIHRyeSBkaWZmZXJlbnQgbW9kZWxzLgoKVGhlIGZpcnN0IHRoaW5nIHdlIGRvIGlzIGRlZmluZSB3aGF0IHR5cGUgb2YgbW9kZWwgd2Ugd291bGQgbGlrZSB0byB1c2UuIFNlZSBbaGVyZV0oaHR0cHM6Ly90aWR5bW9kZWxzLmdpdGh1Yi5pby9wYXJzbmlwL2FydGljbGVzL2FydGljbGVzL01vZGVscy5odG1sCil7dGFyZ2V0PSJfYmxhbmsifSBmb3IgbW9kZWxpbmcgW29wdGlvbnNdaW4gcGFyc25pcC4KCmBgYHtyfQpQTV9tb2RlbCA8LSBwYXJzbmlwOjpsaW5lYXJfcmVnKCkgI1BNIGZvciBwYXJ0aWN1bGF0ZSBtYXRlcgpQTV9tb2RlbApgYGAKCk9LLiBTbyBmYXIgYWxsIHdlIGhhdmUgdG9sZCBgcGFyc25pcGAgaXMgd2Ugd2FudCB0byB1c2UgYSBsaW5lYXIgcmVncmVzc2lvbi4uLiAgTGV0J3MgdGVsbCBgcGFyc25pcGAgbW9yZSBhYm91dCB3aGF0IHdlIHdhbnQuCgpXZSB3b3VsZCBsaWtlIHRvIHVzZSB0aGUgb3JkaW5hcnkgbGVhc3Qgc3F1YXJlcyBtZXRob2QgdG8gZml0IG91ciBsaW5lYXIgcmVncmVzc2lvbi4gU28gd2Ugd2lsbCB0ZWxsIGBwYXJzbmlwYCB0aGF0IHdlIHdhbnQgdG8gdXNlIHRoZSBgbG1gIHBhY2thZ2UgdG8gaW1wbGVtZW50IG91ciBsaW5lYXIgcmVncmVzc2lvbiAodGhlcmUgYXJlIG1hbnkgb3B0aW9ucyBhY3R1YWxseS0gc3VjaCBhcyBbYHJzdGFuYF0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3JzdGFuL3ZpZ25ldHRlcy9yc3Rhbi5odG1sKSBbYGdsbW5ldGBdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9nbG1uZXQvaW5kZXguaHRtbCksIFtga2VyYXNgXShodHRwczovL2tlcmFzLnJzdHVkaW8uY29tLyksIGFuZCBbYHNwYXJrbHlyYF0oaHR0cHM6Ly90aGVyaW5zcGFyay5jb20vc3RhcnRpbmcuaHRtbCNzdGFydGluZy1zcGFya2x5ci1oZWxsby13b3JsZCkpLiBXZSB3aWxsIGRvIHNvIGJ5IHVzaW5nIHRoZSBgc2V0X2VuZ2luZSgpYCBmdW5jdGlvbiBvZiB0aGUgYHBhcnNuaXBgIHBhY2thZ2UuCgpgYGB7cn0KbG1fUE1fbW9kZWwgPC0gCiAgUE1fbW9kZWwgICU+JQogIHBhcnNuaXA6OnNldF9lbmdpbmUoImxtIikKCmxtX1BNX21vZGVsCgpgYGAKCkluIHNvbWUgY2FzZXMgc29tZSBwYWNrYWdlcyBjYW4gZG8gZWl0aGVyIGNsYXNzaWZpY2F0aW9uIG9yIHByZWRpY3Rpb24sIHNvIGl0IGlzIGEgZ29vZCBpZGVhIHRvIHNwZWNpZnkgd2hpY2ggbW9kZSB5b3UgaW50ZW5kIHRvIHBlcmZvcm0uIFlvdSBjYW4gZG8gdGhpcyB3aXRoIHRoZSBgc2V0X21vZGUoKWAgZnVuY3Rpb24gb2YgdGhlIGBwYXJzbmlwYCBwYWNrYWdlLCBieSB1c2luZyBlaXRoZXIgYHNldF9tb2RlKCJjbGFzc2lmaWNhdGlvbiIpYCBvciBgc2V0X21vZGUoInJlZ3Jlc3Npb24iKWAuCgpgYGB7cn0KbG1fUE1fbW9kZWwgPC0gCiAgUE1fbW9kZWwgICU+JQogIHBhcnNuaXA6OnNldF9lbmdpbmUoImxtIikgJT4lCiAgc2V0X21vZGUoInJlZ3Jlc3Npb24iKQoKbG1fUE1fbW9kZWwKCmBgYAoKIyMjIEZpdHRpbmcgdGhlIE1vZGVsOiB0d28gd2F5cyAtIGB3b3JrZmxvd3NgIGFuZCBgcGFyc25pcGAKClRoZXJlIGFyZSB0d28gdwpUbyBmaXQgb3VyIG1vZGVsIHdlIGNhbiB1c2UgdGhlIGBwYXJzbmlwYCBwYWNrYWdlIGFuZCB0aGVuIGFzc2VzcyBvdXIgZml0IHVzaW5nIHRoZSBgeWFyZHN0aWNrYCBwYWNrYWdlLgoKSG93ZXZlciBhIG5ld2VyIHBhY2thZ2UgY2FsbGVkIGB3b3JrZmxvd3NgIGFsbG93cyB1cyB0byBrZWVwIHRyYWNrIG9mIGJvdGggb3VyIHByZXByb2Nlc3Npbmcgc3RlcHMgYW5kIG91ciBtb2RlbCBzcGVjaWZpY2F0aW9uLiBJdCBhbHNvIGFsbG93cyB1cyB0byBpbXBsZW1lbnQgZmFuY2llciBvcHRpbWl6YXRpb25zIGluIGFuIGF1dG9tYXRlZCB3YXkgYW5kIGl0IGlzIGN1cnJlbnRseSBiZWluZyBkZXZlbG9wZWQgdG8gYWxzbyBoYW5kbGUgcG9zdC1wcm9jZXNzaW5nIG9wZXJhdGlvbnMsIHNvIGl0IGlzIGdvb2QgdG8gbGVhcm4gYWJvdXQgaXQhCgpTbyB3ZSB3aWxsIG5vdyBjcmVhdGUgYSB3b3JrZmxvdyB3aXRoIHRoZSByZWNpcGUgKG91ciBwcmVwcm9jZXNzaW5nIHNwZWNpZmljYXRpb25zKSB0aGF0IHdlIG1hZGUgYW5kIHRoZSBtb2RlbCB0aGF0IHdlIGp1c3Qgc3BlY2lmaWVkLgoKRmlyc3Qgd2UgdXNlIHRoZSBgd29ya2Zsb3coKWAgZnVuY3Rpb24gb2YgdGhlIGB3b3JrZmxvd3NgIHBhY2thZ2UgdG8gY3JlYXRlIGEgd29ya2Zsb3cuCgpUaGVuIHdlIGFkZCBvdXIgcmVjaXBlIHdpdGggdGhlIGBhZGRfcmVjaXBlKClgIGZ1bmN0aW9uIGFuZCB3ZSBhZGQgb3VyIG1vZGVsIHdpdGggdGhlIGBhZGRfbW9kZWwoKWAgZnVuY3Rpb24gb2YgdGhlIGB3b3JrZmxvd3NgIHBhY2thZ2UuIAoKTm90ZTogV2UgZG8gbm90IG5lZWQgdG8gYWN0dWFsbHkgcHJlcCBvdXIgcmVjaXBlIGJlZm9yZSB1c2luZyB3b3JrZmxvd3MhCgpgYGB7cn0KUE1fd2Zsb3cgPC13b3JrZmxvd3M6OndvcmtmbG93KCkgJT4lCiAgICAgICAgICAgd29ya2Zsb3dzOjphZGRfcmVjaXBlKG5vdmVsX3JlYykgJT4lCiAgICAgICAgICAgd29ya2Zsb3dzOjphZGRfbW9kZWwobG1fUE1fbW9kZWwpClBNX3dmbG93CmBgYAoKQWgsIG5pY2UuIE5vdGljZSBob3cgaXQgdGVsbHMgdXMgYWJvdXQgYm90aCBvdXIgcHJlcHJvY2Vzc2luZyBzdGVwcyBhbmQgb3VyIG1vZGVsIHNwZWNpZmljYXRpb25zLgoKTm93IHdlIGNhbiBwcmVwYXJlIHRoZSByZWNpcGUgKGVzdGltYXRlIHRoZSBwYXJhbWV0ZXJzKSBhbmQgZml0IHRoZSBtb2RlbCB0byBvdXIgdHJhaW5pbmcgZGF0YSBhbGwgYXQgb25jZS4gUHJpbnRpbmcgdGhlIG91dHB1dCB3ZSBjYW4gc2VlIHRoZSBjb2VmZmljaWVudHMgb2YgdGhlIG1vZGVsLgoKYGBge3J9ClBNX3dmbG93X2ZpdCA8LSBwYXJzbmlwOjpmaXQoUE1fd2Zsb3csIGRhdGEgPSB0cmFpbl9wbSkKUE1fd2Zsb3dfZml0CmBgYAoKT3RoZXJ3aXNlIHdlIGNvdWxkIGhhdmUgZG9uZSB0aGlzIHdpdGhvdXQgdGhlIGB3b3JrZmxvd3NgIHBhY2thZ2UuIE5vdGljZSBoZXJlIHdlIHdpbGwgdXNlZCB0aGUgcHJvY2Vzc2VkIHRyYWluaW5nIGRhdGEgKGBqdWljZWRfdHJhaW5gKSBhcyBvcHBvc2VkIHRvIHRoZSByYXcgdHJhaW5pbmcgZGF0YSB0aGF0IHdlIHVzZWQgd2l0aCB0aGUgd29ya2Zsb3cgd2UgY3JlYXRlZCB3aXRoIGB3b3JrZmxvd3NgLgoKUmVtZW1iZXIgdGhhdCBpbiB0aGlzIGNhc2UsIHdlIG5lZWQgdG8gd3JpdGUgeW91ciBtb2RlbCBhZ2FpbiEgUmVjYWxsIHRoYXQgYGlkYCBhbmQgYGZpcHNgIGFyZSBJRCB2YXJpYWJsZXMgYW5kIHRoYXQgYHZhbHVlc2AgaXMgb3VyIG91dGNvbWUgb2YgaW50ZXJlc3QgKHRoZSBwbSBhaXIgcG9sbHV0aW9uIG1lYXN1cmUgYXQgZWFjaCBtb25pdG9yKS4gCgpgYGB7cn0KanVpY2VkX3RyYWluX3JlYWR5IDwtIGp1aWNlZF90cmFpbiU+JSBzZWxlY3QoIC1pZCwgLWZpcHMpClBNX2ZpdCA8LSBsbV9QTV9tb2RlbCAlPiUgCnBhcnNuaXA6OmZpdCh2YWx1ZSB+LiwgZGF0YSA9anVpY2VkX3RyYWluX3JlYWR5KQoKYGBgCgojIyMgTG9va2luZyBhdCBtb2RlbCBmaXQgd2l0aCBgYnJvb21gCgpUaGUgYGJyb29tYCBwYWNrYWdlIGFsbG93cyBmb3IgYW4gZWFzeS90aWR5IHdheSB0byBsb29rIGF0IHRoZSBmaXR0ZWQgbW9kZWw6ICAKCmB0aWR5KClgIGdyYWJzIHRoZSBjb2VmZmljaWVudHMgZnJvbSB0aGUgbW9kZWwgIApgZ2xhbmNlKClgIHN1bW1hcml6ZXMgdGhlIG1vZGVsIGZpdCBhbmQgZ2l2ZXMgdXMgYW4gaWRlYSBhYm91dCBob3cgd2VsbCB0aGUgbW9kZWwgbWlnaHQgcGVyZm9ybQpgYXVnbWVudCgpYCBnaXZlcyBhIDE1MCByb3cgb2JzZXJ2YXRpb24gbGV2ZWwgc3VtbWFyeSBvZiB0aGUgZGF0YSBhbmQgZml0IAoKVGhlc2UgYGJyb29tYCBmdW5jdGlvbnMgY3VycmVudGx5IG9ubHkgd29yayB3aXRoIGBwYXJzbmlwYCBvYmplY3RzIG5vdCByYXcgYHdvcmtmbG93c2Agb2JqZWN0cy4gVG8gdXNlIHRoZSBgdGlkeSgpYCBmdW5jdGlvbiB3aXRoIGB3b3JrZmxvd3NgIHdlIG5lZWQgdG8gZmlyc3QgdXNlIHRoZSBgcHVsbF93b3JrZmxvd19maXQoKWAgZnVuY3Rpb24uCgpgYGB7cn0KYnJvb206OnRpZHkoUE1fZml0KSAlPiUgYXJyYW5nZShwLnZhbHVlKQpicm9vbTo6Z2xhbmNlKFBNX2ZpdFtbImZpdCJdXSkKYnJvb206OmF1Z21lbnQoUE1fZml0W1siZml0Il1dKSAjIHRoaXMgYWxzbyBnaXZlcyB1cyB0aGUgZml0dGVkIHZhbHVlcywgc3RhbmRhcmQgZXJyb3IgZm9yIGVhY2ggYW5kIG1vcmUhCgoKd2Zsb3dvdXRwdXQ8LVBNX3dmbG93X2ZpdCAlPiUgCiAgcHVsbF93b3JrZmxvd19maXQoKSAlPiUgCiAgYnJvb206OnRpZHkoKSAKCgojVGhlIG91dHB1dCBpcyBpZGVudGljYWwgdXNpbmcgd29ya2Zsb3dzIHRvIGZpdCB0aGUgbW9kZWwgb3IganVzdCBwYXJzbmlwCmlkZW50aWNhbCh0aWR5KFBNX2ZpdCksIHdmbG93b3V0cHV0KQoKYGBgCgoKT0ssIHNvIHdlIGhhdmUgZml0IG91ciBtb2RlbCBvbiBvdXIgdHJhaW5pbmcgZGF0YSwgd2hpY2ggbWVhbnMgd2UgaGF2ZSBjcmVhdGVkIGEgbW9kZWwgdG8gcHJlZGljdCB2YWx1ZXMgb2YgYWlyIHBvbGx1dGlvbiBiYXNlZCBvbiB0aGUgcHJlZGljdG9ycyB0aGF0IHdlIGhhdmUgaW5jbHVkZWQuIFlheSEKCkxldCdzIHRha2UgYSBsb29rIGF0IGhvdyB3ZWxsIG91ciBtb2RlbCBmaXQgb3VyIHRyYWluaW5nIGRhdGE6CgpgYGB7cn0KIyN1c2luZyB0aGUgcGFyc25pcCB2ZXJzaW9uCiNjYW4gZ3JhYiB0aGUgZml0dGVkIHZhbHVlcyBzaW1wbHkgbGlrZSB0aGlzOgpwYXJzbmlwX2ZpdHRlZF92YWx1ZXM8LWZpdHRlZChQTV9maXRbWyJmaXQiXV0pCgpwYXJzbmlwX2ZpdHRlZF92YWx1ZXMKCiNjYW4gYWxzbyBnZXQgdGhlIHZhbHVlcyB1c2luZyB0aGUgYXVnbWVudCBmdW5jdGlvbgpwYXJzbmlwX2ZpdHRlZF92YWx1ZXMgPC0gYXVnbWVudChQTV9maXRbWyJmaXQiXV0sIGRhdGEgPSBqdWljZWRfdHJhaW4pICU+JSAKc2VsZWN0KHZhbHVlLCAuZml0dGVkOi5zdGQucmVzaWQpCgpwYXJzbmlwX2ZpdHRlZF92YWx1ZXMKCiMjdXNpbmcgdGhlIHdvcmtmbG93cyB2ZXJzaW9uCndmX2ZpdCA8LVBNX3dmbG93X2ZpdCAlPiUgCiAgcHVsbF93b3JrZmxvd19maXQoKQoKI2NhbiBncmFiIHRoZSBmaXR0ZWQgdmFsdWVzIHNpbXBseSBsaWtlIHRoaXM6CndmX2ZpdHRlZF92YWx1ZXM8LWZpdHRlZCh3Zl9maXRbWyJmaXQiXV0pCgp3Zl9maXR0ZWRfdmFsdWVzCgojY2FuIGFsc28gZ2V0IHRoZSB2YWx1ZXMgdXNpbmcgdGhlIGF1Z21lbnQgZnVuY3Rpb24Kd2ZfZml0dGVkX3ZhbHVlcyA8LWF1Z21lbnQod2ZfZml0W1siZml0Il1dLCBkYXRhID0ganVpY2VkX3RyYWluKSAlPiUgCnNlbGVjdCh2YWx1ZSwgLmZpdHRlZDouc3RkLnJlc2lkKQoKd2ZfZml0dGVkX3ZhbHVlcwoKI2dpdmVzIHVzIHRoZSBzYW1lIGZpdHRlZCB2YWx1ZXMKaWRlbnRpY2FsKHBhcnNuaXBfZml0dGVkX3ZhbHVlcywgd2ZfZml0dGVkX3ZhbHVlcykKCiMjIExldCdzIG1ha2UgYSBwbG90IG9mIGZpdHRlZCBhbmQgcmVhbCB2YWx1ZXMKCmdncGxvdCh3Zl9maXR0ZWRfdmFsdWVzLCBhZXMoeCA9IC5maXR0ZWQsIHkgPSB2YWx1ZSkpICsgZ2VvbV9wb2ludCgpCmBgYAoKT2ssIHNvIG91ciBmaXR0ZWQgcmFuZ2UgYXBwZWFycyB0byBiZSBzbWFsbGVyIHRoYW4gdGhlIHJlYWwgdmFsdWVzLiBXZSBjb3VsZCBwcm9iYWJseSBkbyBhIGJpdCBiZXR0ZXIuCgpBdCB0aGlzIHBvaW50IHdlIGNvdWxkIHRha2UgYSBsb29rIGF0IHRoZSBhY2N1cmFjeSBvZiBvdXIgbW9kZWwgcGVyZm9ybWFuY2UsIGJ1dCB3ZSB3aWxsIG9ubHkgaGF2ZSBvbmUgcmVmZXJlbmNlIHBvaW50OiBvdXIgdGVzdGluZyBkYXRhc2V0LiBBbmQgd2UgaGF2ZW4ndCBkb25lIGFueSB0dW5pbmcgb2Ygb3VyIG1vZGVsIG9yIGNyb3NzIHZhbGlkYXRpb24uLi4gc28gZ2VuZXJhbGx5IHNwZWFraW5nIHlvdSA8dT4qKnNob3VsZCBub3QqKjwvdT4gZG8gdGhpcy4gCgpIb3dldmVyIGlmIHlvdSB3ZXJlIHNob3J0IG9uIHRpbWUgeW91IGNvdWxkIGNvbnRpbnVlIGxpa2UgdGhpcy4KClVzaW5nIHRoZSB3b3JrZmxvd3MgbWV0aG9kLCB5b3Ugd291bGQgbmVlZCBmdW5jdGlvbnMgbGlrZSB0aGlzOiBgdHVuZTo6dHVuZV8qKClgLCBgdHVuZTo6Zml0X3Jlc2FtcGxlcygpYCBvciBgdHVuZTo6bGFzdF9maXQoKWAgZnJvbSB0aGUgYHR1bmVgIHBhY2thZ2UgdG8gZ2V0IGFuIGFzc2Vzc21lbnQgb2YgZml0LgoKV2UgY291bGQgc3RvcCBoZXJlIGFuZCB1c2UgdGhlIGB5YXJkc3RpY2tgIHBhY2thZ2UgdG8gZXZhbHVhdGUgcGVyZm9ybWFuY2UuIEZpcnN0IHdlIHdvdWxkIHdhbnQgdG8gdXNlIHRoZSBtb2RlbCB0byBwcmVkaWN0IHZhbHVlcyBmb3IgdGhlIG1vbml0b3JzIGluIHRoZSB0ZXN0aW5nIGRhdGEuCgpVc2luZyBwYXJzbmlwIHdlIG5lZWQgdG8gdXNlIHRoZSBiYWtlZCBkYXRhIHRlc3RpbmcgZGF0YS4KCmBgYHtyfQogYmFrZWRfdGVzdF9wbV9yZWFkeSA8LWJha2VkX3Rlc3RfcG0gJT4lc2VsZWN0KCAtImlkIiwgLSJmaXBzIikKIHZhbHVlc19wcmVkX3BhcnNuaXAgPC1wcmVkaWN0KFBNX2ZpdCwgYmFrZWRfdGVzdF9wbV9yZWFkeSkKIHZhbHVlc19wcmVkX3BhcnNuaXAKIAojIHVzaW5nIHRoZSB3b3JrZmxvd3MgdmVyc2lvbgp2YWx1ZXNfcHJlZF93ZnMgPC0gCiAgcHJlZGljdChQTV93Zmxvd19maXQsIHRlc3RfcG0pICU+JSAKICBiaW5kX2NvbHModGVzdF9wbSAlPiUgc2VsZWN0KHZhbHVlLCBmaXBzKSkgCnZhbHVlc19wcmVkX3dmcwoKYGBgCgpMZXQncyB0YWtlIGEgbG9vayBhdCBob3cgd2VsbCBpdCBkaWQ6CmBgYHtyfQojTkVFRCB0byBmaWxsIHRoaXMgaW4KYGBgCgoKU2F5IHdlIHdlcmUgZG9uZSBvcHRpbWl6aW5nIG91ciBwYXJhbWV0ZXJzIHdlIGNvdWxkIHRoZW4gdXNlIHRoZSBgbGFzdF9maXQoKWAgZnVuY3Rpb24gb2YgdGhlIGB3b3JrZmxvd3NgIHBhY2thZ2UuCgojIyMjIHsuc2Nyb2xsYWJsZSB9CmBgYHtyfQpvdmVyYWxsZml0IDwtdHVuZTo6bGFzdF9maXQoUE1fd2Zsb3csIHBtX3NwbGl0KQogIyBvcgpvdmVyYWxsZml0IDwtUE1fd2Zsb3cgJT4lCiAgdHVuZTo6bGFzdF9maXQocG1fc3BsaXQpCgojI292ZXJhbGxmaXQKYGBgCgpXZSBjb3VsZCBjaGVjayBvdXQgdGVzdCBwZXJmb3JtYW5jZSB1c2luZyB0aGUgYGNvbGxlY3RfbWV0cmljcygpYCBmdW5jdGlvbiBvZiB0aGUgYHR1bmVgIHBhY2thZ2UuCgptb2RlbCBwZXJmb3JtYW5jZSA6aHR0cHM6Ly9tZWRpdW0uY29tL0BsaW1hdmFsbGFudGluL21ldHJpY3MtdG8tbWVhc3VyZS1tYWNoaW5lLWxlYXJuaW5nLW1vZGVsLXBlcmZvcm1hbmNlLWU4Yzk2MzY2NTQ3NgoKYGBge3J9CiN0ZXN0X3BlcmZvcm1hbmNlIDwtIG92ZXJhbGxmaXQgICU+JXR1bmU6OmNvbGxlY3RfbWV0cmljcygpCiN0ZXN0X3BlcmZvcm1hbmNlCmBgYAoKSGVyZSB5b3UgY2FuIHNlZSB0aGUgcHJlZGljdGlvbnMgZm9yIHRoZSB0ZXN0IHNldCAodGhlIDI5MiByb3dzIHdpdGggcHJlZGljaXRpb25zIG91dCBvZiB0aGUgODc2IG9yaWdpbmFsIG1vbml0b3IgdmFsdWVzKSBhbHNvIHVzaW5nIHRoZSBgdHVuZWAgcGFja2FnZSB3aXRoIHRoZSBgY29sbGVjdF9wcmVkaWN0aW9ucygpYCBmdW5jdGlvbi4KCmBgYHtyfQojdGVzdF9wcmVkaWN0aW9ucyA8LSBvdmVyYWxsZml0ICAlPiV0dW5lOjpjb2xsZWN0X3ByZWRpY3Rpb25zKCkKI3ByaW50KHRlc3RfcHJlZGljdGlvbnMsIG49MWUzKQpgYGAKIyMjIwoKCkhvd2V2ZXIgd2Ugd291bGQgcmVhbGx5IHdhbnQgdG8gdHVuZSBwYXJhbWV0ZXJzIGFuZCB1c2UgY3Jvc3MgdmFsaWRhdGlvbiBmb3IgdGhpcy4KCgoKeWFyZHN0aWNrIGNhbid0IHRhbGsgZGlyZWN0bHkgdG8gd29ya2Zsb3dzLi4uIG5lZWQgdHVuZSBmb3IgdGhhdC4uLgoKCgojIyMgQ3Jvc3MgdmFsaWRhdGlvbiBzYW1wbGUgc3BsaXR0aW5nCgpXZSB3aWxsIHVzZSB0aGUgYHJzYW1wbGVgIHBhY2thZ2UgYWdhaW4gaW4gb3JkZXIgdG8gZnVydGhlciBpbXBsZW1lbnQgd2hhdCBhcmUgY2FsbGVkIFtjcm9zcyB2YWxpZGF0aW9uXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Dcm9zcy12YWxpZGF0aW9uXyhzdGF0aXN0aWNzKSl7dGFyZ2V0PSJfYmxhbmsifSB0ZWNobmlxdWVzLiBUaGlzIGlzIGFsc28gY2FsbGVkICoqcmVzYW1wbGluZyoqIG9yICoqcmVwYXJ0aW9uaW5nKiouCk5vdGU6IHdlIGFyZSBub3QgYWN0dWFsbHkgZ2V0dGluZyBuZXcgc2FtcGxlcyBmcm9tIHRoZSB1bmRlcmx5aW5nIGRpc3RyaWJ1dGlvbiBzbyB0aGUgdGVybSByZXNhbXBsaW5nIGlzIGEgYml0IG9mIGEgbWlzbm9tZXIuCgpbQ3Jvc3MgdmFsaWRhdGlvbl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ3Jvc3MtdmFsaWRhdGlvbl8oc3RhdGlzdGljcykpe3RhcmdldD0iX2JsYW5rIn0gc3BsaXRzIG91ciB0cmFpbmluZyBkYXRhIGludG8gbXVsdGlwbGUgdHJhaW5pbmcgZGF0YSBzZXRzIHRvIGFsbG93IGZvciBhbiBhc3Nlc3NtZW50IG9mIHRoZSBhY2N1cmFjeSBvZiB0aGUgbW9kZWwuCgpIZXJlIGlzIGEgdmlzdWFsaXphdGlvbiBvZiB0aGUgY29uY2VwdCBmb3IgY3Jvc3MgdmFsaWRhdGlvbi9yZXNhbXBsaW5nL3JlcGFydGl0aW9uaW5nIGZyb20gW01heCBLdWhuXShodHRwczovL3Jlc291cmNlcy5yc3R1ZGlvLmNvbS9hdXRob3JzL21heC1rdWhuKXt0YXJnZXQ9Il9ibGFuayJ9OgoKYGBge3IsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iODAwcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJyZXNhbXBsaW5nLnBuZyIpKQpgYGAKClRlY2huaWNhbGx5IGNyZWF0aW5nIG91ciB0ZXN0aW5nIGFuZCB0cmFpbmluZyBzZXQgb3V0IG9mIG91ciBvcmlnaW5hbCB0cmFpbmluZyBkYXRhIGlzIHNvbWV0aW1lcyBjb25zaWRlcmVkIGEgZm9ybSBvZiBbY3Jvc3MgdmFsaWRhdGlvbl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ3Jvc3MtdmFsaWRhdGlvbl8oc3RhdGlzdGljcykpe3RhcmdldD0iX2JsYW5rIn0gY2FsbGVkIHRoZSBob2xkb3V0IG1ldGhvZC4gQXMgd2UganVzdCBsZWFybmVkIHRoaXMgY2FuIGdpdmUgdXMgYSBiZXR0ZXIgc2Vuc2Ugb2YgdGhlIGFjY3VyYWN5IG9mIG91ciBkYXRhIGluIGEgbW9yZSBnZW5lcmFsaXphYmxlIHdheS4gCgpIb3dldmVyLCB3ZSBjYW4gZG8gYSBiZXR0ZXIgam9iIG9mIG9wdGltaXppbmcgb3VyIG1vZGVsIGZvciBhY2N1cmFjeSBpZiB3ZSBhbHNvIHBlcmZvcm0gYW5vdGhlciB0eXBlIG9mIFtjcm9zcyB2YWxpZGF0aW9uXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Dcm9zcy12YWxpZGF0aW9uXyhzdGF0aXN0aWNzKSl7dGFyZ2V0PSJfYmxhbmsifSBvbiB0aGUgbmV3bHkgZGVmaW5lZCB0cmFpbmluZyBzZXQgdGhhdCB3ZSBqdXN0IGNyZWF0ZWQuIFRoZXJlIGFyZSBtYW55IFtjcm9zcyB2YWxpZGF0aW9uXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Dcm9zcy12YWxpZGF0aW9uXyhzdGF0aXN0aWNzKSl7dGFyZ2V0PSJfYmxhbmsifSBtZXRob2RzIGFuZCBtb3N0IGNhbiBiZSBlYXNpbHkgaW1wbGVtZW50ZWQgdXNpbmcgYHJzYW1wbGVzYCBwYWNrYWdlLiBXZSB3aWxsIHVzZSBhIHZlcnkgcG9wdWxhciBtZXRob2QgY2FsbGVkIGVpdGhlciBbay1mb2xkIG9yIHYtZm9sZCBjcm9zcyB2YWxpZGF0aW9uXShodHRwczovL21hY2hpbmVsZWFybmluZ21hc3RlcnkuY29tL2stZm9sZC1jcm9zcy12YWxpZGF0aW9uLyl7dGFyZ2V0PSJfYmxhbmsifS4gCgpUaGlzIG1ldGhvZCBpbnZvbHZlcyBlc3NlbnRpYWxseSBwcmVmb3JtaW5nIHRoZSBob2xkIG91dCBtZXRob2QgaXRlcmF0aXZlbHkgd2l0aCB0aGUgdHJhaW5pbmcgZGF0YS4gCgpGaXJzdCB0aGUgdHJhaW5pbmcgc2V0IGlzIGRpdmlkZWQgaW50byBrIG9yIHYgZXF1YWxseSBzaXplZCBzbWFsbGVyIHBpZWNlcy4gCgpUaGVuIHRoZSBtb2RlbCBpcyB0cmFpbmVkIG9uIHRoZSBtb2RlbCBvbiBrLTEgb3Igdi0xIHN1YnNldHMgb2YgdGhlIGRhdGEgaXRlcmF0aXZlbHkgKHJlbW92aW5nIGEgZGlmZmVyZW50IHYgb3IgayB1bnRpbGwgYWxsIHBvc3NpYmxlIGstMSBvciB2LTEgc2V0cyBoYXZlIGJlZW4gZXZhbHVhdGVkKSB0byBnZXQgYSBzZW5zZSBvZiB0aGUgcGVyZm9ybWFuY2Ugb2YgdGhlIG1vZGVsLiBUaGlzIGlzIHJlYWxseSB1c2VmdWwgZm9yIGZpbmUgdHVuaW5nIHNwZWNpZmljIGFzcGVjdHMgb2YgdGhlIG1vZGVsIGluIGEgcHJvY2VzcyBjYWxsZWQgbW9kZWwgdHVuaW5nLgoKCkhlcmUgaXMgYSB2aXN1YWxpemF0aW9uIG9mIGhvdyB0aGUgZm9sZHMgYXJlIGNyZWF0ZWQ6CgpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI4MDBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsInZmb2xkLnBuZyIpKQpgYGAKCgpOb3RlOiBQZW9wbGUgdHlwaWNhbGx5IGlnbm9yZSBzcGF0aWFsIGRlcGVuZGVuY2Ugd2l0aCBjcm9zcyB2YWxpZGF0aW9uIG9mIGFpciBwb2xsdXRpb24gbW9uaXRvcmluZyBkYXRhIGluIHRoZSBhaXIgcG9sbHV0aW9uIGZpZWxkLCBzbyB3ZSB3aWxsIGRvIHRoZSBzYW1lLiAgSG93ZXZlciwgaXQgbWlnaHQgbWFrZSBzZW5zZSB0byBsZWF2ZSBvdXQgYmxvY2tzIG9mIG1vbml0b3JzIHJhdGhlciB0aGFuICByYW5kb20gaW5kaXZpZHVhbCBtb25pdG9ycyB0byBoZWxwIGFjY291bnQgZm9yIHNvbWUgc3BhdGlhbCBkZXBlbmRlbmNlLgoKVGhlIFtgdmZvbGRfY3YoKWBdKGh0dHBzOi8vdGlkeW1vZGVscy5naXRodWIuaW8vcnNhbXBsZS9yZWZlcmVuY2UvdmZvbGRfY3YuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSBmdW5jdGlvbiBvZiB0aGUgYHJzYW1wbGVgIHBhY2thZ2UgY2FuIGJlIHVzZWQgdG8gcGFyc2UgdGhlIHRyYWluaW5nIGRhdGEgaW50byBmb2xkcyBmb3Igay1mb2xkL3YtZm9sZCBjcm9zcyB2YWxpZGF0aW9uLgoKVGhlIGB2YCBhcmd1bWVudCBzcGVjaWZpZXMgdGhlIG51bWJlciBvZiBmb2xkcyB0byBjcmVhdGUuClRoZSBgcmVwZWF0c2AgYXJndW1lbnQgc3BlY2lmaWVzIGlmIGFueSBzYW1wbGVzIHNob3VsZCBiZSByZXBlYXRlZCBhY3Jvc3MgZm9sZHMgLSBkZWZ1YWx0IGlzIGBGQUxTRWAKVGhlIGBzdHJhdGFgIGFyZ3VtZW50IHNwZWNpZmllcyBhIHZhcmlhYmxlIHRvIHN0cmF0aWZ5IHNhbXBsZXMgYWNyb3NzIGZvbGRzIChqdXN0IGxpa2UgaW4gYGluaXRpYWxfc3BsaXQoKWApLgoKQWdhaW4gYmVjYXVzZSB0aGVzZSBhcmUgY3JlYXRlZCBhdCByYW5kb20sIHdlIG5lZWQgdG8gdXNlIHRoZSBiYXNlIGBzZXQuc2VlZCgpYCBmdW5jdGlvbiBpbiBvcmRlciB0byBvYnRhaW4gdGhlIHNhbWUgcmVzdWx0cyBlYWNoIHRpbWUgd2Uga25pdCB0aGlzIGRvY3VtZW50LiBHZW5lcmFsbHkgc3BlYWtpbmcgdXNpbmcgMTAgZm9sZHMgaXMgZ29vZCBwcmFjdGljZSwgYnV0IHRoaXMgZGVwZW5kcyBvbiB0aGUgdmFyaWFibGl0eSB3aXRoaW4geW91ciBkYXRhLiBXZSBhcmUgZ29pbmcgdG8gdXNlIDQgZm9yIHRoZSBzYWtlIG9mIGV4cGVkaWVuY3kuIAoKYGBge3J9CnNldC5zZWVkKDEyMzQpCgp2Zm9sZF9wbSA8LXJzYW1wbGU6OnZmb2xkX2N2KGRhdGEgPSB0cmFpbl9wbSwgdiA9IDQpCgp2Zm9sZF9wbQoKCnZmb2xkX3BtJHNwbGl0cyRgMWAKdmZvbGRfcG0kc3BsaXRzJGAyYApgYGAKCk9uY2UgdGhlIGZvbGRzIGFyZSBjcmVhdGVkIHRoZXkgY2FuIGJlIHVzZWQgdG8gZXZhbHVhdGUgcGVmb3JtYW5jZSBieSBmaXR0aW5nIHRoZSBtb2RlbCB0byBlYWNoIG9mIHRoZSByZXNhbXBsZXMgdGhhdCB3ZSBjcmVhdGVkOgoKCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjgwMHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwiY3Jvc3NfdmFsaWRhdGlvbi5wbmciKSkKYGBgCgoKV2UgY2FuIGZpdCB0aGUgbW9kZWwgdG8gb3VyIGNyb3NzIHZhbGlkYXRpb24gZm9sZHMgdXNpbmcgdGhlIGBmaXRfcmVzYW1wbGVzKClgIGZ1bmN0aW9uIG9mIHRoZSBgdHVuZWAgcGFja2FnZSwgYnkgc3BlY2lmeWluZyBvdXIgd29ya2Zsb3cgb2JqZWN0IGFuZCB0aGUgY3Jvc3MgdmFsaWRhdGlvbiBmb2xkIG9iamVjdCB3ZSBqdXN0IGNyZWF0ZWQuIFNlZSBbaGVyZV0oaHR0cHM6Ly90aWR5bW9kZWxzLmdpdGh1Yi5pby90dW5lL3JlZmVyZW5jZS9maXRfcmVzYW1wbGVzLmh0bWwpIGZvciBtb3JlIGluZm9ybWF0aW9uLgoKYGBge3J9CmNvbnRyb2wgPC0gY29udHJvbF9yZXNhbXBsZXMoc2F2ZV9wcmVkID0gVFJVRSkKcmVzYW1wbGVfZml0IDwtdHVuZTo6Zml0X3Jlc2FtcGxlcyhQTV93ZmxvdywgdmZvbGRfcG0pCgpgYGAKCldlIGNhbiBub3cgdGFrZSBhIGxvb2sgYXQgdmFyaW91cyBtZXRyaWNzIG9mIHBlcmZvcm1hbmNlIGJhc2VkIG9uIHRoZSBmaXQgb2Ygb3VyIDEwIGNyb3NzIHZhbGlkYXRpb24gInJlc2FtcGxlcyIuIFRvIGRvIHRoaXMgd2Ugd2lsbCB1c2UgdGhlIGBzaG93X2Jlc3QoKWAgZnVuY3Rpb24gb2YgdGhlIGB0dW5lYCBwYWNrYWdlLgoKYGBge3J9CnR1bmU6OnNob3dfYmVzdChyZXNhbXBsZV9maXQsIG1ldHJpYyA9ICJybXNlIiwgInJzcSIpCmBgYAoKIyMjIFR1bmluZwoKTm93IGxldCdzIHRyeSBzb21lIHR1bmluZy4KCkxldCdzIHRha2UgYSBjbG9zZXIgbG9vayBhdCBob3cgdGhlIG1vbml0b3IgdmFsdWVzIHZhcnkgd2l0aCBsYXRpdHVkZSBhbmQgbG9uZ2l0dWRlLgoKYGBge3J9Cgp0cmFpbl9wbSAlPiUgCiAgZHBseXI6OnNlbGVjdCh2YWx1ZSwgbG9uLCBsYXQpICU+JSAKICB0aWR5cjo6cGl2b3RfbG9uZ2VyKGNvbHMgPSBjKGxvbiwgbGF0KSwgCiAgICAgICAgICAgICAgICAgICAgICBuYW1lc190byA9ICJwcmVkaWN0b3IiLCB2YWx1ZXNfdG8gPSAibG9jX3ZhbHVlIikgJT4lIAogIGdncGxvdChhZXMoeCA9IGxvY192YWx1ZSwgdmFsdWUpKSArIAogIGdlb21fcG9pbnQoYWxwaGEgPSAuMikgKyAKICBnZW9tX3Ntb290aChzZSA9IEZBTFNFKSArIAogICNzY2FsZV95X2xvZzEwKCkgKwogIGZhY2V0X3dyYXAofiBwcmVkaWN0b3IsIHNjYWxlcyA9ICJmcmVlX3giKQpgYGAKCldlIGNhbiBzZWUgdGhhdCB0aGVyZSBkb2VzIG5vdCBhcHBlYXIgdG8gYmUgYSBzaW5nbGUgbGluZWFyIHJlbGF0aW9uc2hpcCBmb3IgZWl0aGVyIG9mIHRoZXNlIHByZWRpY3RvcnMuIFRodXMgd2UgbWlnaHQgd2FudCB0byB0aGluayBhYm91dCB1c2luZyAgW3NwbGluZXNdKGh0dHBzOi8vd3d3Lm1hdGgudWguZWR1L35qaW5ncWl1L21hdGg0MzY0L3NwbGluZS5wZGYpIG9yIHRoaXMoaHR0cHM6Ly90b3dhcmRzZGF0YXNjaWVuY2UuY29tL251bWVyaWNhbC1pbnRlcnBvbGF0aW9uLW5hdHVyYWwtY3ViaWMtc3BsaW5lLTUyYzExNTdiOThhYykgb3IganVzdCB0aGlzKGh0dHBzOi8vdGlkeW1vZGVscy5naXRodWIuaW8vdHVuZS9hcnRpY2xlcy9nZXR0aW5nX3N0YXJ0ZWQuaHRtbCkgb3IgdGhpcyhodHRwczovL3d3dy5wc3ljaC5tY2dpbGwuY2EvbWlzYy9mZGEvZXgtYmFzaXMtYjEuaHRtbCkgdG8gbW9kZWwgdGhlIHJlbGF0aW9uc2hpcCBpbiBvdXIgdHJhaW5pbmcgZGF0YSBtb3JlIGNsb3NlbHkuIEZvciBleGFtcGxlIGZvciB0aGUgbGF0aXR1ZGUgcGxvdCAobGVmdCkgaWYgd2UgaGFkIDIgbGluZXMgYW5kIG9uZSBicmVha3BvaW50IGNhbGxlZCBhIGtub3QgYXJvdW5kIDQwLCB3aXRoIHRoZSBmaXJzdCBsaW5lIGhhdmluZyBhIHBvc2l0aXZlIHNsb3BlIGFuZCB0aGUgc2Vjb25kIHdpdGggYSBuZWdhdGl2ZSBzbG9wZSB0aGlzIHdvdWxkIGZpdCB0aGUgZGF0YSBtb3JlIHNpbWlsYXJseSB0byB0aGUgYmx1ZSBsaW5lIHNob3duIGluIHRoZSBmaWd1cmUuCgpXZSBjYW4gdHVuZSBmb3IgdGhlIG51bWJlciBvZiBrbm90cyBieSB1c2luZyBhIHN0ZXAgZnVuY3Rpb24gaW4gdGhlIGByZWNpcGVzYCBwYWNrYWdlIGNhbGxlZCBgc3RlcF9ucygpYCB3aGVyZSBucyBzdGFuZHMgZm9yIG5hdHVyYWwgc3BsaW5lcy4gSW4gb3JkZXIgdG8gdHVuZSBmb3IgdGhlIG51bWJlciBvZiBrbm90cyBvciBkZWdyZWVzIG9mIGZyZWVkb20sIHdlIGNhbiBzZXQgdGhlIGBkZWdfZnJlZWAgYXJndW1lbnQgdG8gYHR1bmUoKWAuIFRoaXMgaXMgaGVscGZ1bCwgYmVjdWFzZSB3ZSBhcmVuJ3QgZXhhY3RseSBzdXJlIGhvdyBjbG9zZWx5IHdlIHNob3VsZCBiZSBmb2xsb3dpbmcgdGhlIHJlbGF0aW9uc2hpcCB3aXRoIHRoZSB2YWx1ZSBhbmQgb3VyIGxvbmdpdHVkZSBhbmQgbGF0aXR1ZGUgZGF0YSBpbiBvdXIgdHJhaW5pbmcgZGF0YSB0byBhY2hpZXZlIGdvb2QgYWNjdXJhY3kgeWV0IGtlZXAgb3VyIG1vZGVsIGdlbmVyYWxpemFibGUgZm9yIG90aGVyIGRhdGEuIAoKVGhpcyBpcyB3aGVuIG91ciBjcm9zcyB2YWxpZGF0aW9uIG1ldGhvZHMgYmVjb21lIHJlYWxseSBoYW5keS4gV2UgY2FuIHRlc3Qgb3V0IGRpZmZlcmVudCB2YWx1ZXMgZm9yIHRoZSBgZGVnX2ZyZWVgIGFyZ3VtZW50IGFuZCBzZWUgaG93IG91ciBtb2RlbCBwZXJmb3JtYW5jZSB2YXJpZXMgYWNyb3NzIG91ciB0cmFpbmluZyBmb2xkcyB0byB0cnkgdG8gZmluZCB0aGUgb3B0aW1hbCB2YWx1ZS4KCldlIHdpbGwgdXBkYXRlIG91ciByZWNpcGUgdG8gYWRkIHRoZXNlIHN0ZXBzLiBJdCBpcyBhIGdvb2QgaWRlYSB0byBkbyB0aGlzIGZvciBpbmRpdmlkdWFsIHByZWRpY3RvcnMgYmVjYXVzZSB5b3UgY2FuIG5hbWUgZWFjaCB3aXRoIHRoZSBgdHVuZWAgYXJndW1lbnQgc28gdGhhdCB5b3UgY2FuIGtlZXAgdHJhY2sgb2YgaXQgbGF0ZXIuIFdlIGNhbiBzZWUgd2hhdCB3ZSBpbnRlbmQgdG8gdHVuZSB3aXRoIHRoZSBgcGFyYW1ldGVycygpYCBmdW5jdGlvbiBvZiB0aGUgYGRpYWxzYCBwYWNrYWdlLiAKClNlZSBbaGVyZV0odGhpcyhodHRwczovL3RpZHltb2RlbHMuZ2l0aHViLmlvL3R1bmUvYXJ0aWNsZXMvZ2V0dGluZ19zdGFydGVkLmh0bWwpKSBmb3IgbW9yZSBpbmZvcm1hdGlvbiBhYm91dCBpbXBsZW1lbnRpbmcgdGhpcyBpbiB0aWR5bW9kZWxzLgoKYGBge3J9Cgpub3ZlbF9yZWMgJTw+JQogIHN0ZXBfbnMobG9uLCBkZWdfZnJlZSA9IHR1bmUoImxvbiBkZiIpKSAlPiUKICBzdGVwX25zKGxhdCwgIGRlZ19mcmVlID0gdHVuZSgibGF0IGRmIikpCiMgbm92ZWxfcmVjICU8PiUKIyAgIHN0ZXBfbnMobGF0LCAgZGVnX2ZyZWUgPSB0dW5lKCkpCiMgbm92ZWxfcmVjCgpwbV9wYXJhbSA8LWRpYWxzOjpwYXJhbWV0ZXJzKG5vdmVsX3JlYykKcG1fcGFyYW0KYGBgCkdlbmVhcmxseSB5b3UgY291bGQgdXNlIHRoZSBgZ3JpZF8qKClgIGZ1bmN0aW9ucyBvZiB0aGUgYGRpYWxzYCBwYWNrYWdlIHRvIGNyZWF0ZSB0aGUgZGlmZmVyZW50IGNvbWJpbmF0aW9ucyBvZiBkZWdyZWVzIG9mIGZyZWVkb20gdG8gdGVzdCBmb3IgYm90aCB2YXJpYWJsZXMgdG8gb3B0aW1pemUgdGhlIG1vZGVsLiBJbiBvdXIgY2FzZSB3ZSBjYW4gdmlzYWJseSBzZWUgdGhhdCBpZiB3ZSBhZGQgbW9yZSB0aGFuIHNheSA0IG9yIDUgZGVncmVlcyBvZiBmcmVlZG9tIHdlIHdpbGwgbGlrZWx5IG92ZXJmaXQgdGhlIGRhdGEuIFNvIGluc3RlYWQgb2YgdXNpbmcgdGhlc2UgZnVuY3Rpb25zIHdlIHdpbGwgY3JlYXRlIG91ciBvd24gZ3JpZCB1c2luZyB0aGUgYmFzZSBgc2VxKClgIGFuZCBgZXhwYW5kLmdyaWQoKWAgZnVuY3Rpb25zLgoKYGBge3J9CiNhbiBleGFtcGxlIG9mIHdoYXQgeW91IGNvdWxkIGRvOgojc3BsaW5lX2dyaWQgPC1kaWFsczo6Z3JpZF9yZWd1bGFyKHBtX3BhcmFtLCBsZXZlbHMgPSAzKQpkZl92YWxzIDwtIHNlcSgxLCA1LCBieSA9IDIpCnNwbGluZV9ncmlkIDwtIGV4cGFuZC5ncmlkKGBsb24gZGZgID0gZGZfdmFscywgYGxhdCBkZmAgPSBkZl92YWxzKQpzcGxpbmVfZ3JpZApgYGAKCgpOb3cgd2Ugd2lsbCB0dW5lIHRoaXMgaHlwZXItcGFyYW1ldGVyIChkZWdyZWVzIG9mIGZyZWVkb20pIGZvciBib3RoIHRoZSBgbGF0YCBhbmQgYGxvbmAgdmFyaWFibGVzIHVzaW5nIG91ciBjcm9zcyB2YWxpZGF0aW9uIGZvbGRzLiBUbyBkbyB0aGlzIHdlIHdpbGwgdXNlIHRoZSBgdHVuZV9ncmlkKClgIGZ1bmN0aW9uIG9mIHRoZSBgdHVuZWAgcGFja2FnZS4KCmBgYHtyfQoKZGZfdHVuaW5nIDwtbG1fUE1fbW9kZWwgJT4lIAogIHR1bmU6OnR1bmVfZ3JpZChub3ZlbF9yZWMsIHJlc2FtcGxlcyA9dmZvbGRfcG0sIAogICAgICAgICAgICAgICAgICBncmlkID0gc3BsaW5lX2dyaWQpCgojZGZfdHVuaW5nIDwtUE1fd2Zsb3cgJT4lIHR1bmU6OnR1bmVfZ3JpZChyZXNhbXBsZXMgPXZmb2xkX3BtLCAKICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JpZCA9IHNwbGluZV9ncmlkLCAKICAKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhcmFtX3NldCA9cG1fcGFyYW0pCgpkZl90dW5pbmcKYGBgCgoKCmBgYHtyfQoKZGZfdHVuaW5nICU+JQogIGNvbGxlY3RfbWV0cmljcygpCgpjb2xsZWN0X21ldHJpY3MoZGZfdHVuaW5nKQpzaG93X2Jlc3QoZGZfdHVuaW5nLCBtZXRyaWMgPSAicm1zZSIsIG4gPTEpCmBgYAoKCiMjIyBMaW5lYXIgUmVncmVzc2lvbiBNb2RlbCB3aXRoIFBDQQoKV2UgY2FuIGNyZWF0ZSBhbm90aGVyIHdvcmtmbG93IHRvIHNlZSBob3cgbW9kZWwgcGVmcm9tYW5jZSBjb21wYXJlcyB1c2luZyBhIGRpZmZlcmVudCBtb2RlbC4gSW4gdGhpcyBjYXNlIHdlIGFyZSBnb2luZyB0byBwZWZvcm0gc29tZXRoaW5nIGNhbGxlZCBQcmluY2lwYWwgQ29tcG9uZW50IEFuYWx5c2lzIG9yIFBDQS4gCgpTbyB3aGF0IGlzIFBDQT8KCmBgYHtyfQpsbV9QQ0FfcmVjIDwtcmVjaXBlKHRyYWluX3BtKSAlPiUKICAgIHVwZGF0ZV9yb2xlKGV2ZXJ5dGhpbmcoKSwgbmV3X3JvbGUgPSAicHJlZGljdG9yIiklPiUKICAgIHVwZGF0ZV9yb2xlKHZhbHVlLCBuZXdfcm9sZSA9ICJvdXRjb21lIiklPiUKICAgIHVwZGF0ZV9yb2xlKGlkLCBuZXdfcm9sZSA9ICJpZCB2YXJpYWJsZSIpICU+JQogICAgdXBkYXRlX3JvbGUoImZpcHMiLCBuZXdfcm9sZSA9ICJjb3VudHkgaWQiKSAlPiUKICAgIHN0ZXBfZHVtbXkoc3RhdGUsIGNvdW50eSwgY2l0eSwgemN0YSkgJT4lCiAgICBzdGVwX3BjYShhbGxfcHJlZGljdG9ycygpKSAKYGBgCgpMZXQncyB0YWtlIGEgbG9vayB0byBzZWUgd2hhdCB0aGUgYHN0ZXBfcGNhYCBmdW5jdGlvbiBkb2VzIHRvIG91ciBwcmVkaWN0b3JzLiBUbyBkbyBzbyByZWNhbGwgdGhhdCB3ZSBuZWVkIHRvIHVzZSB0aGUgYHByZXBgIGFuZCBganVpY2VgICBmdW5jdGlvbnMgb2YgdGhlIGByZWNpcGVzYCBwYWNrYWdlICBvbiBvdXIgcmVjaXBlLgoKYGBge3J9CnByZXBwZWRfcmVjIDwtIHByZXAobG1fUENBX3JlYywgdmVyYm9zZSA9IFRSVUUsIHJldGFpbiA9IFRSVUUgKQpqdWljZWRfdHJhaW48LSBqdWljZShwcmVwcGVkX3JlYykKZ2xpbXBzZShqdWljZWRfdHJhaW4pCmBgYAoKV2Ugc3RpbGwgd2FudCB0byB1c2UgdGhlIGBsbWAgcGFja2FnZSBmb3Igb3VyIHJlZ3Jlc3Npb24gc28gd2UgY2FuIHVzZSB0aGUgc2FtZSBtb2RlbCBvYmplY3Q6CmBgYHtyfQpsbV9QTV9tb2RlbApgYGAKCmBgYHtyfQpwY2Ffd2Zsb3cgPC13b3JrZmxvd3M6OndvcmtmbG93KCkgJT4lCiAgICAgICAgICAgIHdvcmtmbG93czo6YWRkX3JlY2lwZShsbV9QQ0FfcmVjKSAlPiUKICAgICAgICAgICAgd29ya2Zsb3dzOjphZGRfbW9kZWwobG1fUE1fbW9kZWwpCnBjYV93ZmxvdwpgYGAKClJlbWVtYmVyIHRoYXQgdXNpbmcgYHdvcmtmbG93c2Agd2UgZG9udCBhY3R1YWxseSBuZWVkIHRvIHByZXAgb3VyIHJlY2lwZSwgd2UgY2FuIGp1c3QgZml0IG91ciBtb2RlbCBkaXJlY3RseS4gU28gbm93IHdlIHdpbGwgdXNlIHR1bmUgdG8gZml0IG91ciByZXNhbXBsZXMuLi4gV0FJVCBET0VTIFRISVMgV09SSz8/IG9yIGRvIHlvdSBuZWVkIHRvIHVzZSBmaXQuLi4KCkZpdCB0aGUgY3Jvc3MgdmFsaWRhdGlvbiBzYW1wbGVzOgoKYGBge3J9CnJlc2FtcGxlX3BjYV9maXQgPC10dW5lOjpmaXRfcmVzYW1wbGVzKHBjYV93ZmxvdywgdmZvbGRfcG0pCmBgYAoKCkxvb2sgYXQgdGhlIHBlcmZvcm1hbmNlOgpgYGB7cn0KY29sbGVjdF9tZXRyaWNzKHJlc2FtcGxlX3BjYV9maXQpCmBgYAoKQW5kIHdlIGNhbiBjb21wYXJlIHRoaXMgd2l0aCBvdXIgcHJldmlvdXMgcGVyZm9ybWFuY2U6CgpgYGB7cn0KY29sbGVjdF9tZXRyaWNzKHJlc2FtcGxlX2ZpdCkKYGBgCgpTbyB3ZSBjYW4gc2VlIHRoYXQgb3VyIHBlcmZvcm1hbmNlIGlzbid0IHF1aXRlIGFzIGdvb2QgLSBlc3BlY2lhbGx5IGlmIHdlIGxvb2sgYXQgdGhlIGBybXNlYCB2YWx1ZS4gIAoKTGV0J3MgcmV2aWV3IGV2ZXJ5dGhpbmc6CgpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI4MDBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsInRpZHltb2RlbHNfZWNvc3lzdGVtLnBuZyIpKQpgYGAKCgoKCj4gY2hlY2tfbmV3X3ZhbHVlczogVGhpcyBjaGVjayB3aWxsIGJyZWFrIHRoZSBiYWtlIGZ1bmN0aW9uIGlmIGFueSBvZiB0aGUgY2hlY2tlZCBjb2x1bW5zIGRvZXMgY29udGFpbiB2YWx1ZXMgaXQgZGlkCm5vdCBjb250YWluIHdoZW4gcHJlcCB3YXMgY2FsbGVkIG9uIHRoZSByZWNpcGUuIElmIHRoZSBjaGVjayBwYXNzZXMsIG5vdGhpbmcgaXMgY2hhbmdlZCB0byB0aGUgZGF0YQoKPiBjaGVja19yYW5nZSBjcmVhdGVzIGEgc3BlY2lmaWNhdGlvbiBvZiBhIHJlY2lwZSBjaGVjayB0aGF0IHdpbGwgY2hlY2sgaWYgdGhlIHJhbmdlIG9mIGEgbnVtZXJpYwp2YXJpYWJsZSBjaGFuZ2VkIGluIHRoZSBuZXcgZGF0YS4KCgoKW3BhcmFtZXRlciB2cyBoeXBlcnBhcmFtZXRlcl0oaHR0cHM6Ly93d3cuZGF0YWNhbXAuY29tL2NvbW11bml0eS90dXRvcmlhbHMvcGFyYW1ldGVyLW9wdGltaXphdGlvbi1tYWNoaW5lLWxlYXJuaW5nLW1vZGVscyl7dGFyZ2V0PSJfYmxhbmsifQoKCgpwcmVwcGVyIGZvciBjcm9zcyB2YWxpZGF0aW9uPwoKCgoKCgpncmVhdCBibG9nIGFib3V0IGNyb3NzIHZhbGlkYXRpb24gZXRjIGh0dHBzOi8vdG93YXJkc2RhdGFzY2llbmNlLmNvbS90cmFpbi10ZXN0LXNwbGl0LWFuZC1jcm9zcy12YWxpZGF0aW9uLWluLXB5dGhvbi04MGI2MWJlY2E0YjYKCiMjIERhdGEgVmlzdWFsaXphdGlvbgoKIyMgU3VtbWFyeQoKV2UgaGF2ZSBldmFsdWF0ZWQgYXZlcmFnZSBjb25zdW1wdGlvbiBlc3RpbWF0ZXMgb2YgMTUgZGlldGFyeSBmYWN0b3JzIHdpdGggcHJvYmFibHkgbm9uLWNvbW11bmljYWJsZSBkaXNlYXNlIChOQ0QpIHJpc2sgZnJvbSAxOTUgZGlmZmVyZW50IGNvdW50cmllcyBhcm91bmQgdGhlIHdvcmxkLiBUbyBkbyBzbyB3ZSBpbXBvcnRlZCBkYXRhIGZyb20gYSBQREYgdXNpbmcgdGhlIGBwZGZ0b29sc2AgcGFja2FnZSwgYXMgd2VsbCBhcyBkYXRhIGZyb20gdHdvIENTViBmaWxlcyB1c2luZyByZWFkci4gV2UgdXNlZCBgdGlkeXZlcnNlYCBwYWNrYWdlcyBzdWNoIGFzIGBkcGx5cmAsIGBzdHJpbmdyYCwgYW5kIGB0aWR5YCB0byBjbGVhbiBhbmQgam9pbiB0aGUgZGF0YSBmcm9tIHRoZSBQREYgd2l0aCB0aGUgQ1NWIGZpbGVzLiAKCldlIGxlYXJuZWQgdGhhdCBSZWdyZXNzaW9uIGlzIGEgcG93ZXJmdWwgYW5kIGZsZXhpYmxlIHN0YXRpc3RpY2FsIHRvb2wgdGhhdCBzaW1wbGlmaWVzIG9yIGVzdGltYXRlcyB0aGUgcmVsYXRpb25zaGlwcyBiZXR3ZWVuIHZhcmlhYmxlcyB1c2luZyBhIG1hdGhlbWF0aWNhbCBtb2RlbC4gV2UgbGVhcm5lZCBhYm91dCB0aGUgdXRpbGl0eSBvZiB0aGUgcmVncmVzc2lvbiB0byBjb21wYXJlIGdyb3VwcywgbG9vayBmb3IgYXNzb2NpYXRpb25zIGJldHdlZW4gdmFyaWFibGVzLCBhbmQgdG8gcHJlZGljdCBvdXRjb21lcyBiYXNlZCBvbiBtdWx0aXBsZSBwcmVkaWN0b3Igb3IgZXhwbGFuYXRvcnkgdmFyaWFibGVzLiBXZSB0aGVuIGNvbXBhcmVkIHRoaXMgdG8gb3RoZXIgcG9wdWxhciB0ZXN0cyBsaWtlIHRoZSAkdCQtdGVzdCBhbmQgdGhlIEFOT1ZBLiBXZSBsZWFybmVkIHRoYXQgdGhlc2UgdGVzdHMgYXJlIGFjdHVhbGx5IGVxdWl2YWxlbnQgdG8gc3BlY2lhbGl6ZWQgdHlwZXMgb2YgcmVncmVzc2lvbnMuCgpPdXIgc3RhdGlzdGljYWwgYW5hbHlzaXMgZm9jdXNlZCBvbiBldmFsdWF0aW5nIGRpZmZlcmVuY2VzIGluIHRoZSBjb25zdW1wdGlvbiBvZiByZWQgbWVhdCBhcm91bmQgdGhlIHdvcmxkIGJldHdlZW4gZmVtYWxlcyBhbmQgbWFsZXMgYW5kIGFjcm9zcyBkaWZmZXJlbnQgYWdlIGdyb3Vwcy4gRmlyc3Qgd2UgbG9va2VkIGF0IHRoZSBhc3N1bXB0aW9ucyBvZiBbJHQkLXRlc3RzXShodHRwczovL3N0YXR0cmVrLmNvbS9zdGF0aXN0aWNzL2RpY3Rpb25hcnkuYXNweD9kZWZpbml0aW9uPXR3by1zYW1wbGUlMjAkdCQtdGVzdCl7dGFyZ2V0PSJfYmxhbmsifSBhbmQgcmVncmVzc2lvbnMsIGFuZCBkZXRlcm1pbmVkIHRoYXQgdGhlIHJlbGF0aXZlIHBlcmNlbnRhZ2UgZGF0YSBvZiByZWQgbWVhdCBjb25zdW1wdGlvbiB0byB0aGUgb3B0aW1hbCBndWlkZWxpbmUgc3VnZ2VzdGVkIGFtb3VudCB3YXMgcmlnaHQgc2tld2VkLiBXZSBsZWFybmVkIHRoYXQgd2UgY291bGQgdHJhbnNmb3JtIHRoZSBkYXRhIGJ5IHRha2luZyB0aGUgbG9nIG9mIHRoZXNlIHZhbHVlcyB0byBhY2hpZXZlIG1vcmUgbm9ybWFsbHkgZGlzdHJpYnV0ZWQgZGF0YS4gVG8gY29tcGFyZSBtYWxlcyBhbmQgZmVtYWxlcyB3ZSB1c2VkIGEgJHQkLXRlc3QgYW5kIGxlYXJuZWQgdGhhdCBhICR0JC10ZXN0IGlzIGEgc3BlY2lhbGl6ZWQgZm9ybSBvZiBhIGxpbmVhciByZWdyZXNzaW9uLiBUbyBjb21wYXJlIHRoZSAxNSBkaWZmZXJlbnQgYWdlIGdyb3VwcyB3ZSB1c2VkIGFuIEFOT1ZBIGFuZCBsZWFybmVkIHRoYXQgdGhlIEFOT1ZBIGlzIGFsc28gYSBzcGVjaWFsaXplZCBmb3JtIG9mIGxpbmVhciByZWdyZXNzaW9uLiBXZSBleGFtaW5lZCBob3cgd2Ugb2J0YWluZWQgdGhlIHNhbWUgcmVzdWx0cyB1c2luZyBlaXRoZXIgc3RhdGlzdGljYWwgdGVzdC4gVGhpcyB3YXMgYWxzbyB0aGUgY2FzZSBpZiB3ZSBsb29rZWQgYXQgdGhlIGVmZmVjdCBvZiBnZW5kZXIgYW5kIGNvbnRyb2xsZWQgZm9yIHRoZSBwYWlyZWQgY291bnRyeSBzdHJ1Y3R1cmUgaW4gdGhlIGRhdGEgYnkgZWl0aGVyIGluY2x1ZGluZyBgbG9jYXRpb25fbmFtZWAgaW4gdGhlIG1vZGVsIGFzIGFub3RoZXIgdGVybSBvciBieSB1c2luZyBhIG1peGVkIGVmZmVjdHMgbW9kZWwgdG8gY29udHJvbCBmb3IgdGhpcyBzdHJ1Y3R1cmUgYXMgYSByYW5kb20gZWZmZWN0IGJ1dCBub3Qgc3BlY2lmaWNhbGx5IHRlc3QgZm9yIHRoZSBpbmZsdWVuY2Ugb2YgYGxvY2F0aW9uX25hbWVgIG9uIHJlZCBtZWF0IGNvbnN1bXB0aW9uIGVzdGltYXRlcy4gV2UgbGVhcm5lZCB0aGF0IGZpeGVkIGVmZmVjdHMgYXJlIHRob3NlIHRoYXQgd2Ugd2lzaCB0byBldmFsdWF0ZSwgd2hpbGUgcmFuZG9tIGVmZmVjdHMgYXJlIHRob3NlIHRoYXQgbWF5IGluZmx1ZW5jZSB0aGUgcmVsYXRpb25zaGlwcyBvZiBvdXIgdmFyaWFibGVzIG9mIGludGVyZXN0IGJ1dCB0aGF0IHdlIGRvIG5vdCB3aXNoIHRvIGFjdGl2ZWx5IGV2YWx1YXRlLiBVc2luZyB0aGVzZSB0ZXN0cyBhbmQgbW9kZWxzLCB3ZSBkZXRlcm1pbmVkIHRoYXQgbWFsZXMgY29uc3VtZSBtb3JlIHJlZCBtZWF0IHRoYW4gd29tZW4gb24gYXZlcmFnZSBhcm91bmQgdGhlIHdvcmxkLiAKCk91ciBBTk9WQSBhbmFseXNpcyBvZiBhZ2UgZGV0ZXJtaW5lZCB0aGF0IGluZGVlZCB0aGVyZSBhdCBsZWFzdCBvbmUgYWdlIGdyb3VwIGNvbnN1bWVkIGEgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgYW1vdW50IG9mIHJlZCBtZWF0IGNvbXBhcmVkIHRvIHRoZSBvdGhlciBhZ2UgZ3JvdXBzLCBhbmQgdGhpcyB3YXMgc3RpbGwgdGhlIGNhc2Ugd2hlbiB3ZSBjb250cm9sbGVkIGBsb2NhdGlvbl9uYW1lYC4gSG93ZXZlciwgd2UgbGVhcm5lZCB0aGF0IHdlIGNvdWxkIHRoYXQgdGhlIEFOT1ZBIGRvZXMgbm90IHByb3ZpZGUgaW5mb3JtYXRpb24gYWJvdXQgd2hpY2ggYWdlIGdyb3VwcyBhcmUgZGlmZmVyZW50LiBXZSBsZWFybmVkIGhvdyB0aGUgcmVncmVzc2lvbiBob3dldmVyIGNvdWxkIHByb3ZpZGUgc29tZSBjb21wYXJpc29ucyBvZiBkaWZmZXJlbnQgYWdlIGdyb3VwcyByZWxhdGl2ZSB0byB0aGUgcmVmZXJlbmNlIGFnZSBncm91cC4gRnVydGhlcm1vcmUsIG91ciBkYXRhIHZpc3VhbGl6YXRpb25zIGFsbG93ZWQgdXMgdG8gZGV0ZXJtaW5lIHRoYXQgaW4gZ2VuZXJhbCByZWQgbWV0IGNvbnN1bXB0aW9uIGFwcGVhcnMgdG8gYmUgaGlnaGVyIGluIHRoZSB5b3VuZ2VyIGFnZSBncm91cHMgcmVsYXRpdmUgdG8gdGhlIG9sZGVyIGFnZSBncm91cHMuIAoKRmluYWxseSwgd2UgYWxzbyBsb29rZWQgYXQgZGlmZmVyZW5jZXMgaW4gcmVkIG1lYXQgY29uc3VtcHRpb24gYmV0d2VlbiB0aGUgZGlmZmVyZW50IGNvdW50cmllcyBhbmQgc2F3IGluIG91ciBBTk9WQSBhbmFseXNpcyBhbmQgb3VyIHJlZ3Jlc3Npb24gYW5hbHlzaXMgdGhhdCB0aGVyZSB3ZXJlIHNpZ25pZmljYW50IGRpZmZlcmVuY2VzLiBXZSB3ZXJlIGFibGUgdG8gdXNlIGEgcmVncmVzc2lvbiB0aGF0IGluY2x1ZGVkIGBzZXhgLCBgYWdlX2dyb3VwX25hbWVgLCBhbmQgYGxvY2F0aW9uX25hbWVgIHRvIGV2YWx1YXRlIHRoZSBpbmZsdWVuY2Ugb2YgZWFjaCBvZiB0aGUgdGhyZWUgZGVtb2dyYXBoaWMgZmFjdG9ycyBvbiBjb25zdW1wdGlvbiB3aGlsZSBjb250cm9sbGluZyBvciBhY2NvdW50aW5nIGZvciB0aGUgb3RoZXIgdHdvLiBPdXIgcmVzdWx0cyBkZW1vbnN0cmF0ZWQgdGhhdCBhbGwgdGhyZWUgaW5mbHVlbmNlZCBvciB3ZXJlIGFzc29jaWF0ZWQgd2l0aCByZWQgbWVhdCBjb25zdW1wdGlvbi4KCkluIHByZWZvcm1pbmcgb3VyIHN0YXRpc3RpY2FsIGFuYWx5c2VzIHdlIGxlYXJuZWQgYWJvdXQgdGhlIGFzc3VtcHRpb25zIG9mIHRoZSAkdCQtdGVzdCwgdGhlIHJlZ3Jlc3Npb24sIGFuZCB0aGUgQU5PVkEuIFdlIGFsc28gbGVhcm5lZCBhYm91dCBpbXBvcnRhbnQgbWV0aG9kcyB0byB0ZXN0cyB0aGVzZSBhc3N1bXB0aW9ucy4KCiMjIyMgJHQkLXRlc3QgYXNzdW1wdGlvbnM6CgoxKSBOb3JtYWxpdHkgb2YgdGhlIGRhdGEgZm9yIGJvdGggZ3JvdXBzICh0aGlzIGlzIG5vdCBhcyBtdWNoIG9mIGFuIGlzc3VlIGlmIHRoZSBudW1iZXIgb2Ygb2JzZXJ2YXRpb25zIGlzIHJlbGF0aXZlbHkgbGFyZ2UgdG90YWwgbj4zMCAtIGNhbiBldmFsdWF0ZSBieSBwbG90dGluZyB0aGUgZGlzdHJpYnV0aW9uIGFuZCBieSBjcmVhdGluZyBbUS1RIHBsb3RzXShbUS1RIFBsb3RzXShodHRwOi8vb25saW5lc3RhdGJvb2suY29tLzIvYWR2YW5jZWRfZ3JhcGhzL3EtcV9wbG90cy5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9KSkKMikgRXF1YWwgdmFyaWFuY2UgYmV0d2VlbiB0aGUgdHdvIGdyb3VwcyAobWFrZSBzdXJlIHlvdSBkbyB0aGUgY29ycmVjdCB0ZXN0IGlmIHRoZSBkYXRhIGlzIG5vdCBub3JtYWwpCjMpIEJhbGFuY2VkIHNhbXBsZSBzaXplcyBvZiB0aGUgdHdvIGdyb3Vwcwo0KSBJbmRlcGVuZGVudCBvYnNlcnZhdGlvbnMgKG9yIGluZGVwZW5kZW50IHBhaXJlZCBvYnNlcnZhdGlvbnMpCgpXZSBjYW4gZXZhbHVhdGUgaWYgb3VyIGRhdGEgaXMgW25vcm1hbGx5IGRpc3RyaWJ1dGVkXShodHRwczovL3d3dy5waHlzaW9sb2d5Lm9yZy9kb2kvZnVsbC8xMC4xMTUyL2FkdmFuLjAwMDY0LjIwMTcpe3RhcmdldD0iX2JsYW5rIn0gYnkgcGxvdHRpbmcgdGhlIGRpc3RyaWJ1dGlvbiBhbmQgYnkgY3JlYXRpbmcgW1EtUSBwbG90c10oW1EtUSBQbG90c10oaHR0cDovL29ubGluZXN0YXRib29rLmNvbS8yL2FkdmFuY2VkX2dyYXBocy9xLXFfcGxvdHMuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSB0byBjb21wYXJlIHRoZSBkaXN0cmlidXRpb24gb2Ygb3VyIGRhdGEgdG8gdGhlIHRoZW9yZXRpY2FsIFtub3JtYWwgZGlzdHJpYnV0aW9uXShodHRwczovL3d3dy5waHlzaW9sb2d5Lm9yZy9kb2kvZnVsbC8xMC4xMTUyL2FkdmFuLjAwMDY0LjIwMTcpe3RhcmdldD0iX2JsYW5rIn0uCgo8dT5JZiBvdXIgZGF0YSBpcyBub3Qgbm9ybWFsbHkgZGlzdHJpYnV0ZWQsIHdlIGNhbiBjb25zaWRlciB0aGVzZSBvcHRpb25zOjwvdT4KCjEpIFdlIGNhbiBzdGlsbCBwZXJmb3JtIGEgJHQkLXRlc3QgaWYgb3VyIG4gaXMgbGFyZ2UKMikgV2UgY2FuIHRyYW5zZm9ybSB0aGUgZGF0YSBiZWZvcmUgcGVyZm9ybWluZyBhICR0JC10ZXN0CjMpIFdlIGNhbiB1c2UgYSBub25wYXJhbWV0cmljIHRlc3QgKFdpbGNveG9uIHNpZ25lZCByYW5rIHRlc3QsIHRoZSBXaWxjb3hvbiByYW5rIHN1bSB0ZXN0LCBhbmQgdGhlIFR3by1zYW1wbGUgS29sbW9nb3Jvdi1TbWlybm92IChLUykgdGVzdCkKNCkgV2UgY2FuIHBlcmZvcm0gYSAkdCQtdGVzdCB3aXRoIHJlc2FtcGxpbmcgbWV0aG9kcyAod2hpY2ggc2hvdWxkIGJlIGVzcGVjaWFsbHkgY29uc2lkZXJlZCB3aGVuIHRoZSBncm91cHMgYXJlIGltYmFsYW5jZWQpCgpTZWUgdGhpcyBbY2FzZSBzdHVkeV0oaHR0cHM6Ly9vcGVuY2FzZXN0dWRpZXMuZ2l0aHViLmlvL29jcy1icC1ydXJhbC1hbmQtdXJiYW4tb2Jlc2l0eSl7dGFyZ2V0PSJfYmxhbmsifSBmb3IgbW9yZSBpbmZvcm1hdGlvbiBvbiAkdCQtdGVzdCBhc3N1bXB0aW9ucy4KCldlIGxlYXJuZWQgdGhhdCB3ZSBjYW4gdGVzdCBpZiAyIGdyb3VwcyBoYXZlIGVxdWFsIHZhcmlhbmNlIHVzaW5nOiAgCjEpIHRoZSBGIHRlc3Qgd2l0aCBgdmFyLnRlc3QoKWAgIAoyKSBNb29kJ3MgdGVzdCB1c2luZyBbYG1vb2QudGVzdCgpYF0oaHR0cHM6Ly9maWxlcy5lcmljLmVkLmdvdi9mdWxsdGV4dC9FRDA2NTU1OS5wZGYpICh1c2UgaWYgdGhlIGRhdGEgaXMgbm90IG5vcm1hbGx5IGRpc3RyaWJ1dGVkKSAgCgojIyMjIExpbmVhciByZWdyZXNzaW9uIGFzc3VtcHRpb25zOgoKTCAobGluZWFyKSAtIFRoZXJlIGlzIGEgbGluZWFyIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSB2YXJpYWJsZXMuICAKSSAoaW5kZXBlbmRlbnQpIC0gVGhlIHNhbXBsZXMgYXJlIGluZGVwZW5kZW50IGZyb20gb25lIGFub3RoZXIuICAKTiAobm9ybWFsKSAtIFRoZSByZXNpZHVhbHMgYXJlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkLiAgCkUgKGVxdWFsIHZhcmlhbmNlcykgLSBUaGUgdmFyaWFuY2Ugb2YgdGhlIHJlc2lkdWFscyBvZiB0aGUgZ3JvdXBzIGlzIHNpbWlsYXIuICAgCkl0IGlzIGFsc28gaW1wb3J0YW50IHRoYXQgcHJlZGljdG9yIHZhcmlhYmxlcyBhcmUgbm90IGNvcnJlbGF0ZWQgd2l0aCBvbmUgYW5vdGhlci4gIAoKIyMjIyBBTk9WQSBhc3N1bXB0aW9uczoKCjEpIE5vcm1hbGl0eSBvZiB0aGUgZGF0YSBmb3IgYWxsIHRlc3RlZCBncm91cHMgKGxlc3Mgb2YgYW4gaXNzdWUgaWYgdGhlIG51bWJlciBvZiBvYnNlcnZhdGlvbnMgaXMgcmVsYXRpdmVseSBsYXJnZSB0b3RhbCBuPjMwKSAKMikgRXF1YWwgdmFyaWFuY2UgYmV0d2VlbiB0aGUgZ3JvdXBzIC0gYWthIEhvbW9nZW5laXR5IG9mIHZhcmlhbmNlIChtYWtlIHN1cmUgeW91IGRvIHRoZSBjb3JyZWN0IHRlc3QgaWYgdGhlIGRhdGEgaXMgbm90IG5vcm1hbCkgCjMpIEJhbGFuY2VkIHNhbXBsZSBzaXplcyBvZiB0aGUgZ3JvdXBzIAo0KSBJbmRlcGVuZGVudCBvYnNlcnZhdGlvbnMgKG9yIGluZGVwZW5kZW50IHBhaXJlZCBvYnNlcnZhdGlvbnMpIAoKV2UgbGVhcm5lZCBhYm91dCB0aHJlZSB0ZXN0cyBmb3IgZXhhbWluaW5nIHRoZSBlcXVhbGl0eSBvZiB2YXJpYW5jZSBvZiAzIG9yIG1vcmUgZ3JvdXBzOgoxKSBbQmFydGxldHQncyB0ZXN0XShodHRwczovL3d3dy5pdGwubmlzdC5nb3YvZGl2ODk4L2hhbmRib29rL2VkYS9zZWN0aW9uMy9lZGEzNTcuaHRtKXt0YXJnZXQ9Il9ibGFuayJ9ICh3b3JrcyB3ZWxsIGlmIHRoZSBkYXRhIGFwcGVhcnMgdG8gYmUgbm9ybWFsbHkgZGlzdHJpYnV0ZWQpIAoyKSBbRmxpZ25lci1LaWxsZWVuXShodHRwOi8vd2lraS5zdGF0LnVjbGEuZWR1L3NvY3IvaW5kZXgucGhwL0FQX1N0YXRpc3RpY3NfQ3VycmljdWx1bV8yMDA3X05vblBhcmFtX1ZhckluZGVwKXt0YXJnZXQ9Il9ibGFuayJ9IHRlc3QgaXMgbm9ucGFyYW1ldHJpYyBhbmQgZG9lcyBub3QgYXNzdW1lIG5vcm1hbGl0eSAKMykgW0xldmVuZSdzIHRlc3RdKGh0dHBzOi8vd3d3Lml0bC5uaXN0Lmdvdi9kaXY4OTgvaGFuZGJvb2svZWRhL3NlY3Rpb24zL2VkYTM1YS5odG0pe3RhcmdldD0iX2JsYW5rIn0sIGlzIG1vcmUgcm9idXN0IHRvIHZpb2xhdGlvbnMgb2Ygbm9ybWFsaXR5IHRoYW4gdGhlIEJhcnRsZXR0J3MgdGVzdCwgYnV0IG5vdCBhcyByb2J1c3QgYXMgdGhlIEZsaWduZXItIEtpbGxlZW4gdGVzdCAKCgpVc2luZyB0aGUgYGdncGxvdDJgIHBhY2thZ2Ugd2Ugd2VyZSBhYmxlIHRvIHZpc3VhbGl6ZSB0cmVuZHMgaW4gdGhlIGRhdGEgYW5kIHRvIGNvbXBhcmUgY29uc3VtcHRpb24gb2YgdGhlc2UgZGlldGFyeSBmYWN0b3JzIGluIHRoZSBVUyB3aXRoIHRoYXQgb2YgdGhlIG90aGVyIGNvdW50cmllcy4KV2Ugc2VlIHRoYXQgdGhlIHBvcHVsYXRpb25zIGluIG1hbnkgY291bnRyaWVzIGFyZSBvdmVyLWNvbnN1bWluZyBmb29kcyB0aGF0IGFyZSBhc3NvY2lhdGVkIHdpdGggaGVhbHRoIHJpc2sgd2hlbiBvdmVyLWNvbnN1bWVkLiBJbiBwYXJ0aWN1bGFyIHByb2Nlc3NlZCBtZWF0IGFuZCBzdWdhci1zd2VldGVuZWQgYmV2ZXJhZ2VzIGFwcGVhciB0byBiZSB0aGUgbW9zdCBvdmVyIGNvbnN1bWVkLiBJbXBvcnRhbnRseSBib3RoIG9mIHRoZXNlIGFwcGVhciB0byBiZSBjb25zdW1lZCBhdCBoaWdoZXIgcXVhbnRpdGllcyBieSBtYWxlcyBhbmQgeW91bmdlciBhZHVsdHMuIFBlb3BsZSBpbiB0aGUgVVMgIGFwcGVhciB0byBjb25zdW1lIGxlc3Mgc3VnYXItc3dlZXRlbmVkIGJldmVyYWdlcyB0aGFuIG90aGVyIGNvdW50cmllcywgaG93ZXZlciwgcGVvcGxlIGFyZSBzdGlsbCBvdmVyLWNvbnN1bWluZy4gUHJvY2Vzc2VkIG1lYXQgaG93ZXZlciBhcHBlYXJzIHRvIGJlIGVzcGVjaWFsbHkgYmFkIGluIHRoZSBVUy4gSW4gdGVybXMgb2YgZm9vZCB0aGF0IG5lZWQgdG8gYmUgY29uc3VtZWQgaW4gYWRlcXVhdGUgYW1vdW50cyB0byBvdmVyY29tZSBoZWFsdGggcmlzaywgbmVhcmx5IGFsbCBjb3VudHJpZXMgZm9yIGFsbCBmYWN0b3JzIGFyZSBub3QgcmVhY2hpbmcgZ3VpZGVsaW5lIGxldmVscy4gSG93ZXZlciwgdGhlcmUgYXJlIHNvbWUgY291bnRyaWVzIGNvbnN1bWluZyBtb3JlIHRoYW4gYWRlcXVhdGUgYW1vdW50cyBvZiBsZWd1bWVzLCB2ZWdldGFibGVzLCBmcnVpdHMgYW5kIGZpYmVyLiBQZW9wbGUgaW4gdGhlIFVTIGFwcGVhciB0byBlYXQgbW9yZSBtaWxrIHByb2R1Y3RzIGFuZCBjb25zdW1lIG1vcmUgb21lZ2EtMyBmYXR0eSBhY2lkIGFuZCBjYWxjaXVtIHJpY2ggZm9vZHMgdGhhbiBvdGhlciBjb3VudHJpZXMuIEFsbCBjb3VudHJpZXMgaW5jbHVkaW5nIHRoZSBVUyBjb25zdW1lIHZlcnkgbG93IGxldmVscyBvZiBwb2x5dW5zYXR1cmF0ZWQgZmF0dHkgYWNpZHMuIFRoZXNlIFtwb2x5dW5zYXR1cmF0ZWQgZmF0dHkgYWNpZHNdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1BvbHl1bnNhdHVyYXRlZF9mYXQpIGFyZSBhYnVuZGFudCBpbiBzZWVkcywgbnV0cywgYXZvY2Fkb3MsIGFzIHdlbGwgYXMgZmlzaC4gTGlrZWx5IHRoZSBsb3cgbGV2ZWwgb2YgY29uc3VtcHRpb24gb2YgbnV0cyBhbmQgc2VlZHMgY29udHJpYnV0ZXMgdG8gdGhlc2UgbG93IHBvbHl1bnNhdHVyYXRlZCBmYXR0eSBhY2lkIGVzdGltYXRlcy4gVGhlIHN1cHBsZW1lbnRhcnkgdGFibGUgaW5jbHVkZWQgaW4gdGhlIGFydGljbGUgc3VnZ2VzdHMgdGhhdCBwb29yIGNvbnN1bXB0aW9uIG9mIHBvbHl1bnNhdHVyYXRlZCBmYXR0eSBhY2lkcyBpcyBhc3NvY2lhdGVkIHdpdGggaXNjaGVtaWMgaGVhcnQgZGlzZWFzZS4gVGhlIGFydGljbGUgdGFrZXMgdGhpcyBkYXRhIGZ1cnRoZXIgdG8gZXZhbHVhdGUgdGhlIGFzc29jaWF0aW9uIG9mIGNvbnN1bXB0aW9uIGxldmVscyBvZiB0aGVzZSBmb29kcyB3aXRoIG1vcnRhbGl0eS4KCkFuYWx5c2VzIGxpa2UgdGhlIG9uZSBpbiBvdXIgY2FzZSBzdHVkeSBhcmUgaW1wb3J0YW50IGZvciBkZWZpbmluZyB3aGljaCBncm91cHMgY291bGQgYmVuZWZpdCB0aGUgbW9zdCBmcm9tIGludGVydmVudGlvbnMsIGVkdWNhdGlvbiwgYW5kIHBvbGljeSBjaGFuZ2VzIHdoZW4gYXR0ZW1wdGluZyB0byBtaXRpZ2F0ZSBwdWJsaWMgaGVhbHRoIGNoYWxsZW5nZXMuIFlvdSBjYW4gc2VlIGluIHRoZSBbYXJ0aWNsZV0oaHR0cHM6Ly93d3cudGhlbGFuY2V0LmNvbS9hY3Rpb24vc2hvd1BkZj9waWk9UzAxNDAtNjczNiUyODE5JTI5MzAwNDEtOCl7dGFyZ2V0PSJfYmxhbmsifSBob3dldmVyIHRoYXQgbWFueSBhZGRpdGlvbmFsIGNvbnNpZGVyYXRpb25zIHdvdWxkIGJlIGludm9sdmVkIHRvIHBlcmZvcm0gYSBtb3JlIHRob3JvdWdoIGFuYWx5c2lzIHRvIGFkZXF1YXRlbHkgdW5kZXJzdGFuZCB0aGUgZGF0YSBlbm91Z2ggdG8gcmVjb21tZW5kIHBvbGljeSBjaGFuZ2VzLgoKCiMjIyBTdWdnZXN0ZWQgSG9tZXdvcmsKClN0dWRlbnRzIGNhbiBldmFsdWF0ZSBjb25zdW1wdGlvbiBlc3RpbWF0ZXMgb2YgYW5vdGhlciBkaWV0YXJ5IGZhY3RvciBiZXNpZGVzIHJlZCBtZWF0LgoKIyMjIEhlbHBmdWwgTGlua3MKCnJldmlldyBvZiBbdGlkeW1vZGVsc10oaHR0cHM6Ly9ydmlld3MucnN0dWRpby5jb20vMjAxOS8wNi8xOS9hLWdlbnRsZS1pbnRyby10by10aWR5bW9kZWxzLyl7dGFyZ2V0PSJfYmxhbmsifSAKCmd1aWRlIGZvciBbcHJlcHJvY2Vzc2luZyB3aXRoIHJlY2lwZXNdKGh0dHA6Ly93d3cucmViZWNjYWJhcnRlci5jb20vYmxvZy8yMDE5LTA2LTA2X3ByZV9wcm9jZXNzaW5nLykKCltndWlkZV0oaHR0cHM6Ly9icmlhdHRlLmdpdGh1Yi5pby9nZ2NvcnIvKSBmb3IgdXNpbmcgR0dhbGx5IHRvIGNyZWF0ZSBjb3JyZWxhdGlvbiBwbG90cwpbZ3VpZGVdKGh0dHBzOi8vd3d3LnRpZHl2ZXJzZS5vcmcvYmxvZy8yMDE4LzExL3BhcnNuaXAtMC0wLTEvKSBmb3IgdXNpbmcgcGFyc25pcCB0byB0cnkgZGlmZmVyZW50IGFsZ29yaXRobXMgb3IgZW5naW5lcwpbcmVjaXBlIGZ1bmN0aW9uc10oaHR0cHM6Ly90aWR5bW9kZWxzLmdpdGh1Yi5pby9yZWNpcGVzL3JlZmVyZW5jZS9pbmRleC5odG1sKQoKPHU+VGVybXMgYW5kIGNvbmNlcHRzIGNvdmVyZWQ6PC91PiAgCgpbVGlkeXZlcnNlXShodHRwczovL3d3dy50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgCltSU3R1ZGlvIGNoZWF0c2hlZXRzXShodHRwczovL3JzdHVkaW8uY29tL3Jlc291cmNlcy9jaGVhdHNoZWV0cy8pe3RhcmdldD0iX2JsYW5rIn0gIApbSW5mZXJlbmNlXShodHRwczovL3d3dy5icml0YW5uaWNhLmNvbS9zY2llbmNlL2luZmVyZW5jZS1zdGF0aXN0aWNzKXt0YXJnZXQ9Il9ibGFuayJ9ICAKW1JlZ3Jlc3Npb25dKGh0dHBzOi8vbGluZGVsb2V2LmdpdGh1Yi5pby90ZXN0cy1hcy1saW5lYXIvKXt0YXJnZXQ9Il9ibGFuayJ9ICAKW0RpZmZlcmVudCB0eXBlcyBvZiByZWdyZXNzaW9uXShodHRwczovL3d3dy5hbmFseXRpY3N2aWRoeWEuY29tL2Jsb2cvMjAxNS8wOC9jb21wcmVoZW5zaXZlLWd1aWRlLXJlZ3Jlc3Npb24vKXt0YXJnZXQ9Il9ibGFuayJ9ICAKW09yZGluYXJ5IGxlYXN0IHNxdWFyZXMgbWV0aG9kXShodHRwOi8vc2V0b3NhLmlvL2V2L29yZGluYXJ5LWxlYXN0LXNxdWFyZXMtcmVncmVzc2lvbi8pe3RhcmdldD0iX2JsYW5rIn0gIApbUmVzaWR1YWxdKGh0dHBzOi8vd3d3LnN0YXRpc3RpY3Nob3d0by5kYXRhc2NpZW5jZWNlbnRyYWwuY29tL3Jlc2lkdWFsLyl7dGFyZ2V0PSJfYmxhbmsifSAgCgo8dT5QYWNrYWdlcyB1c2VkIGluIHRoaXMgY2FzZSBzdHVkeTogPC91PgoKIFBhY2thZ2UgICB8IFVzZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKLS0tLS0tLS0tLSB8LS0tLS0tLS0tLS0tLQpbaGVyZV0oaHR0cHM6Ly9naXRodWIuY29tL2plbm55YmMvaGVyZV9oZXJlKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgIHwgdG8gZWFzaWx5IGxvYWQgYW5kIHNhdmUgZGF0YSAgCltyZWFkcl0oaHR0cHM6Ly9yZWFkci50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gaW1wb3J0IHRoZSBDU1YgZmlsZSBkYXRhICAKW2RwbHlyXShodHRwczovL2RwbHlyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byBhcnJhbmdlL2ZpbHRlci9zZWxlY3QvY29tcGFyZSBzcGVjaWZpYyBzdWJzZXRzIG9mIHRoZSBkYXRhICAKW3NraW1yXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvc2tpbXIvaW5kZXguaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gZ2V0IGFuIG92ZXJ2aWV3IG9mIGRhdGEgICAKW3N1bW1hcnl0b29sc10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3NraW1yL2luZGV4Lmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIGdldCBhbiBvdmVydmlldyBvZiBkYXRhIGluIGEgZGlmZmVyZW50IHN0eWxlICAgCltwZGZ0b29sc10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3BkZnRvb2xzL3BkZnRvb2xzLnBkZil7dGFyZ2V0PSJfYmxhbmsifSAgIHwgdG8gcmVhZCBhIFBERiBpbnRvIFIgICAKW21hZ3JpdHRyXShodHRwczovL21hZ3JpdHRyLnRpZHl2ZXJzZS5vcmcvYXJ0aWNsZXMvbWFncml0dHIuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgIHwgdG8gdXNlIHRoZSBgJTw+JWAgcGlwcGluZyBvcGVyYXRvciAgCltwdXJycl0oaHR0cHM6Ly9wdXJyci50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gcGVyZm9ybSBmdW5jdGlvbnMgb24gYWxsIGNvbHVtbnMgb2YgYSB0aWJibGUgICAKW3RpYmJsZV0oaHR0cHM6Ly90aWJibGUudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgIHwgdG8gY3JlYXRlIGRhdGEgb2JqZWN0cyB0aGF0IHdlIGNhbiBtYW5pcHVsYXRlIHdpdGggIGRwbHlyL3N0cmluZ3IvdGlkeXIvcHVycnIgIApbdGlkeXJdKGh0dHBzOi8vdGlkeXIudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIHNlcGFyYXRlIGRhdGEgd2l0aGluIGEgY29sdW1uIGludG8gbXVsdGlwbGUgY29sdW1ucyAKW2dncGxvdDJdKGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICB8IHRvIG1ha2UgdmlzdWFsaXphdGlvbnMgd2l0aCBtdWx0aXBsZSBsYXllcnMgIAoKCkRvIEkgbmVlZCB0byB0YWxrIGFib3V0IG1hY2hpbmUgbGVhcm5pbmcgaW4gZ2VuZXJhbCBtb3JlLi4uIGNsYXNzaWZpY2F0aW9uIHZzIHByZWRpY3Rpb24/